モチベーション
公式チュートリアル [UE4] ブループリント to C++ 公式チュートリアルのメモをまとめました
が、参考までに公式テンプレートのデュアル ジョイスティック シューティング ゲームをブループリントから C++ に変換するだけの私の理解にも従います。
この変換方法は必ずしも優れているわけではありませんが、チュートリアルの変換方法を使用して知識を定着させることができれば幸いです。
準備
1. プロジェクトを作成する
- 最終的には C++ プロジェクトを行うことになりましたが、最初にテンプレートを選択したときにブループリントを選択しました。
2. C++クラスを追加する
- 新しいプロジェクトを作成すると、C++ プロジェクトと比較してコンパイル オプションがないことが簡単にわかります。プロジェクトファイルにソースフォルダーがありません
- したがって、まず新しい C++ クラスを作成し、プロジェクトを C++ プロジェクトに変換する必要があります。
- 最初のステップは、操作している宇宙船を書き直すことです。宇宙船の元の親クラスはポーン クラスなので、最初にポーンを作成します。
3. ブループリントの親をリセットする
- 船内でブループリントの親をリセットするオプションを見つけます。
- 新しく作成されたポーンを見つけて選択すると、新しく作成された C++ クラスが現在のブループリントの親になります。
- 次のステップは、ブループリント内のロジックをクラスに移行することです。
ブループリントに従って C++ を作成する
観測設計図
- イベント グラフでは、イベント ティックの後に操作の長いリストがあり、同時に 2 つの関数があることが簡単にわかります。まずは置換関数から始めましょう。
方法 1: 関数を 1 つずつ書き直す
- まず FireShot 関数を見てみましょう。この関数には入力とベクトル Direction があり、出力はありません。
UFUNCTION(BlueprintCallable)
void FireShot(FVector Direction) ;
- 次に、関数定義を可能な限り宣言して復元します。
- 1 つ目は最初の部分で、ユーザーが発砲できるかどうかを確認するコード ブロックとしてコメント化されています。
- まず最初に、この Can Fire 変数を使用する必要があります。ただし、これは C++ ファイルではなくブループリントで定義されます。したがって、C++ ファイルで作成します。
UPROPERTY(BlueprintReadWrite)
bool CanFire;
- BlueprintReadWrite を使用すると、ブループリントはこの変数を読み書きできます。
- 最初の課題はベクトル長 API から来ており、これは FVector クラスの関連付けを通じて見つけることができます。
思いつかない、あるいは見つからない場合。ブループリントで彼がどのライブラリに属しているかを確認してください。
- C++ ソースコード検索を入力してください
- 検索したところ、ライブラリにnode関数の実装が見つかり、これで事件は解決しました。
void ANewPawn::FireShot(FVector Direction)
{
if(!CanFire) return ;
if(Direction.Size() <= 0) return;
}
- 次に、このブロックのブループリント ロジックを実現します。(現在のコード↑)
方法 2: ブループリントのローカル イベントを使用する
- 2 番目のブロックのロジックは実際には非常に簡単ですが、難しいのが問題です。Actor を生成する機能では、クラスを提供する必要があります。しかし、C++ でクラス アセットを見つけるのは依然として面倒です。
if(!CanFire) return ;
if(Direction.Size() <= 0) return;
FRotator ShipRotator = Direction.ToOrientationRotator() ;
FVector SpawnPoint = GetActorLocation()+Direction.ToOrientationRotator().RotateVector(GunOffset);
FTransform SpawnTransform = FTransform(ShipRotator, SpawnPoint, FVector(1.0f,1.0f,1.0f));
- アクターを生成する前のコードが完成しました。しかし、アクターの生成方法が本当にわからない場合はどうすればよいでしょうか。
- 現時点では、ブループリントのローカル イベントから移動する必要があります。
UFUNCTION(BlueprintCallable,BlueprintNativeEvent)
void FireShot(FVector Direction) ;
- 定義時にBlueprintNativeEventのマクロを追加
void ANewPawn::FireShot_Implementation(FVector Direction)
{
if(!CanFire) return ;
if(Direction.Size() <= 0) return;
FRotator ShipRotator = Direction.ToOrientationRotator() ;
FVector SpawnPoint = GetActorLocation()+Direction.ToOrientationRotator().RotateVector(GunOffset);
SpawnTransform = FTransform(ShipRotator, SpawnPoint, FVector(1.0f,1.0f,1.0f));
}
- 内部の機能を実装するには、FireShot のサフィックスを追加します。
- ここでは便宜上、生成された Transform の変数を作成しました。
- コンパイル後、CanFire などの元の変数は競合を防ぐために _0 になります。一つずつ交換する必要があります。
- C++変数の初期値を設定することを忘れないでください。
- オーバーロードされた関数を追加し、C++ で実装された FireShot を選択します
- 前半は C++ で実装されているため、親クラスの関数も呼び出され、実行が完了してから残りのステップが実行されます。
- つまり、この関数を半分は C++ で実装し、半分はブループリントで実装するように変更しました。
- しかし、そうなると問題が発生するのですが、CanShot ではない場合、ランタイムが直接停止してしまうのです。しかし、私の書き方では、彼は実行を続け、Actor を生成するノードにアクセスします。
bool ANewPawn::FireShot_Implementation(FVector Direction)
{
if(!CanFire) return false;
if(Direction.Size() <= 0) return false;
FRotator ShipRotator = Direction.ToOrientationRotator() ;
FVector SpawnPoint = GetActorLocation()+Direction.ToOrientationRotator().RotateVector(GunOffset);
SpawnTransform = FTransform(ShipRotator, SpawnPoint, FVector(1.0f,1.0f,1.0f));
return true ;
}
- CPPのコードを修正し、bool判定のある関数に変更します。
- リロード後、他の人は元のブループリント ノードを使用します。
- テスト:正常に排出できる
方法 3: ブループリントでイベントを実装できる
- マップ上でのシーン回転の設定などの操作でスケルタル メッシュ ボディにアクセスする必要があると思われる場合は、C++ での実装が容易ではないため、ブループリントに残すこともできます。
UFUNCTION(BlueprintCallable,BlueprintImplementableEvent)
void HandleRotation(FRotator Rotation,FVector NewLocation) ;
- ここでは、ブループリントで実装可能なイベント (マクロ: BlueprintImplementableEvent) に次のコードを配置します。
- 宣言後に直接コンパイルします (これは純粋な仮想関数に似ており、親クラスに実装する必要はありません)。
- サブクラスのブループリントに戻り、オーバーロードを作成します。
- 本来の機能を切り離すことができます。(後で修正したところ、Vector 入力を追加する必要があることが判明し、画像は変更されませんでした)
ティックを書き換える
- これまでの内容を読んで疑問に思った方もいるかもしれませんが、このような面倒な関数の書き換えは C++ を変更し、ブループリントのローカル イベントを使用することになりますが、ブループリントで実現可能なイベントにはどのような意味があるのでしょうか?
- 回答: 私たちの宇宙船では、イベント Tick は通常の main 関数と似ています。上記の方法で書き換えた関数はC++で呼び出すことができ、Tickの書き換えが非常に簡単になります。
- 現在の Tick ロジックには 3 つのステップしかありません: 1. 回転を計算する 2. 関数 HandleRotaion を呼び出す 3. FireShot 関数を呼び出す
void ANewPawn::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
FVector MoveVector = FVector(GetInputAxisValue(FName("MoveForward")),GetInputAxisValue(FName("MoveRight")),0.0f);
MoveVector = MoveVector.GetClampedToMaxSize(1.0f);
MoveVector = MovementSpeed * DeltaTime * MoveVector ;
if(MoveVector.Size() <= 0) return ;
FRotator XRotator = MoveVector.ToOrientationRotator();
//调用蓝图可实现事件HandleRotation
HandleRotation(XRotator,MoveVector);
//调用蓝图本地时间FireVector
FVector FireVector = FVector(GetInputAxisValue(FName("FireForward")),GetInputAxisValue(FName("FireRight")),0.0f);
FireShot(FireVector);
}
// Called to bind functionality to input
void ANewPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
PlayerInputComponent->BindAxis(FName("MoveForward"));
PlayerInputComponent->BindAxis(FName("MoveRight"));
PlayerInputComponent->BindAxis(FName("FireForward"));
PlayerInputComponent->BindAxis(FName("FireRight"));
//不执行这个绑定的话就无法获取输入
}
- 追加するコードは上記の計算ロジックを簡単に実装できます。次に、事前に準備した関数を呼び出すと完了です。
- このようにして、宇宙船は完全に改造されます。
ヒント
- これは単なる個人的な練習であるため、書き方の選択は必ずしも科学的で標準化されているわけではなく、考え方を提供するだけです。
- ブループリント ノードが C++ にどのように対応するかわからない場合は、参照学習用にこのテンプレートの C++ バージョンを作成できます (ただし、公式の C++ 実装が最適ではない可能性があります)。
- もっとやって、もっと貯めてください〜