Unreal Engine におけるキャラクターの構成要素
ゲーム モード / ゲーム ステートのセクションで述べたように、Unreal Engine ゲームプレイ フレームワークは、Unreal Engine におけるキャラクターの動作を理解するのに役立ちます。 概念的には、プレイヤーがゲーム ワールドにおける物理的な存在を表すポーンで構成され、コントローラーがその動作を決定します。 この分離は、AI だけでなくネットワーク レプリケーションにも役立ちます。 参考までに、階層は以下のようになります。
まず、アセットをインポートし、ポーンを作成し、プレイヤー コントローラーまで進めていきましょう。 Parrot の場合、プレイヤーが操作するヒーローは Captain Barbarossa です (Quaternius が提供する Pirate Kit を入手するには、Quaternius のウェブサイトにアクセスしてください)。
アート アセットをインポートする
自分の 3D モデリング ツールで、メッシュ/アニメーションをエンジンと互換性のある形式でエクスポートします。 この場合、デベロッパーは .fbx ファイルを使用しています。 Barbarossa のアセットは「Content/Assets/Quaternius/PirateKit/Characters/Barbarossa」にあります。 .fbx をインポートするには、コンテキスト メニューを右クリックするか、コンテンツ ブラウザにドラッグアンドドロップします。 .fbx ファイルのインポート設定ウィンドウが表示されます。 インポートに適切なオプションを選択します。 今回の場合、既存のスケルトンが選択されていないこと、およびインポート アニメーションにチェックが入っていることを確認してください。 また、メッシュでインデックス付けできる新しいアトラス マテリアルを作成する必要があります。 このマテリアルは、Pirate Kit 内のアセット間で再利用できます。 これで、これら 3 つのファイルと、.fbx ファイルに含まれるアニメーションがすべて揃いました。
わかりやすくするために、アニメーション シーケンス ファイルは、以下の 3 つのファイルに隣接する「Animations」フォルダ内にあります。
スケルトン、スケルタルメッシュ、および物理アセット
スケルトンは、スケルタルメッシュ内のボーン (ジョイントと呼ばれることもあります) を定義するために使用される階層です。 これらのボーンは、3D モデリング ツールのリグと一致する必要があります。 リグに互換性がある限り、スケルトンは複数のスケルタルメッシュ間で再利用できます。 また、物理アセットも作成されます。 物理アセットは、スケルタルメッシュで使用される物理とコリジョンを定義します。 物理アセットには、シミュレーション用の剛体とコンストレイントが含まれます。 スケルタルメッシュごとに物理アセットを 1 つだけ作成でき、条件に応じてオン/オフを切り替えることができます。 物理アセットはインポート時に調整することも、スケルタルメッシュから新しいアセットを作成することもできます。
アニメーション ブループリント
これでスケルタルメッシュが作成できたので、アニメーション ブループリントを使用してアニメーションを作成できます。 アニメーション ブループリントは Unity の Mecanim アニメーション システムと似ています。 アニメーション ブループリントのアニメーション グラフは見た目も機能も似ています。 どちらのシステムにも、アニメーション ステートを最終的な出力ポーズに遷移させる条件付きロジック フローが備わっています。 フォルダ内でコンテキスト メニューから新しいアニメーション ブループリントを作成し、スケルトンを選択します。 このアニメーション ブループリントは、「Content/Blueprints/Player」に ABP_Captain_Barbarossa という名前で保存します。
ブループリント インスペクターの左側には、イベント グラフとアニメーション グラフという 2 つのグラフがあります。 アニメーション グラフは、最終的な出力ポーズを制御するステート マシンです。 イベント グラフでは、アニメーションに関連するあらゆるロジックを定義できます。 Mecanim コンポーネントにデータを渡す必要がある Unity とは異なり、アニメーション ブループリントは特定のイベントで必要なものを取得できます。 たとえば、キャラクターの速度についてクエリを実行し、その値に基づいてアニメーションを駆動するとします。 これを効率的に行うには、イベント グラフでイベント ブループリントの Initialize Animation ノードを使用し、所有アクタを取得し、その移動コンポーネントを変数にキャッシュします。 これにより、BlueprintThreadSafeUpdateAnimation のティックごとに、移動コンポーネントから速度についてクエリを実行できるようになります。 変数はイベント グラフとアニメーション グラフ間で共有することもできます。
Barbarossa 用に設定されたアニメーション ブループリントは、自分でさらに詳しく調べてみる価値があります。 ノードをダブルクリックすると、最終的な出力ポーズに対してステート マシン、ステート、ステート ルールがどのように設定されているかを確認できます。 シーケンス プレーヤーとブレンド スペースの使用例も示されています。 同様に、イベント グラフはアニメーションがキャラクター データによってどのように駆動されるかを示しています。この関係性は、この記事を読み進めていくとより明確になります。
ポーン
これでアニメートできるスケルタルメッシュが作成できたので、ゲーム モードで使用するポーンの作成を開始できます。 デベロッパーは、Unreal Engine のデフォルトのキャラクターをベースに構築することを選択しました。これは、デフォルトの Pawn C++ クラスの子クラスです。 キャラクター クラスには、このゲームで特に便利な Character Movement コンポーネントがあり、これもベースとして構築できます。
プレイヤー ポーンと敵ポーンには、ヒットポイント、被弾、死亡など、いくつかの共通機能があります。 この機能は、ACharacter を継承する AParrotCharacterBase C++ クラスを作成することで共有されます。 敵ポーンとプレイヤー ポーンの動作が異なる場合、このクラスは優れたベースラインとなります。
次に、プレイヤー固有のロジックを処理する AParrotPlayerCharacter C++ クラスを作成します。 最後に、キャラクターのビジュアル表現を処理するブループリントを作成します。 Parrot のブループリントは、「Content/Blueprints/Player」にある BP_ParrotPlayerCharacter です。 継承階層は以下のようになります。
BP_ParrotPlayerCharacter を開くと、エディタ ウィンドウの左側にあるコンポーネント インスペクターの下にいくつかのコンポーネントが表示されます。 メッシュ コンポーネントでは、スケルタルメッシュ アセットと Anim クラスのアニメーション ブループリントを設定できます。 メッシュの位置が正しくない場合は、カプセル コンポーネントに合わせてトランスフォーム値を調整します。 以下のようになっています。
次に、ゲーム モード アセットのブループリントにデフォルトのポーン クラスを割り当てます。
これで、ゲームで使用できるアニメーション ポーンが完成しました。
プレイヤー コントローラー
使用可能なポーンができたら、プレイヤー コントローラーを作成できます。 プレイヤー コントローラーは、基本的にプレイヤーの意志を表します。 ゲームを作成する際に考慮すべき点の 1 つは、入力イベントをどこで定義するかです。 ポーンが変化しないシンプルなゲームであれば、ポーンが適しています。 しかし、動作が複雑になってくると、プレイヤー コントローラーの方が適した選択肢となります。 ポーンは一時的なものであり、プレイヤー コントローラーによって所有されたり、所有されなくなったりします。 プレイヤー コントローラーはゲーム中ずっと存続しますが、ポーンはスポーンまたは破棄されます。
プレイヤー コントローラーには C++ ロジックは不要なので、必要な処理を実行するブループリントを作成します。 BP_ParrotPlayerController は「Content/Blueprints/Player」にあります。 継承階層は以下のようになります。
ブループリント内には、基本的なゲームプレイ ロジックにつながる入力イベント ノードがあります。 これらの入力イベントは、特に Enhanced Input に関連しています。 Enhanced Input の設定方法の詳細については、Enhanced Input のドキュメントを参照してください。 Parrot のプレイヤー キャラクター ポーンをプレイ開始時にキャッシュしておくことで、後で基本の移動関数を呼び出す際に使用できます。 たとえば、Add Movement Input、Jump、および StopJump などです。
では、テストしてみましょう。 ゲームモードの BP で、新しいプレイヤー コントローラー クラスを設定し、ゲーム内でコントローラーが使用できることを確認します。
レベル エディタのこのドロップダウンで、適切なゲーム モードが選択されていることを確認します。
最後に、マップに PlayerStart アクタと、表示可能なカメラがあることを確認します。 プレイ ボタンを押すと、キャラクターが動き回り、アニメートされるのを確認できます。
Parrot キャラクター移動コンポーネント
基本クラス ACharacter には、多くの優れた機能が組み込まれています。 その一例が UCharacterMovement アクタ コンポーネントです。 キャラクター移動コンポーネントは、キャラクターがワールド内をどのように移動するかに関するすべてのロジックを処理します。 歩く、走る、落ちる、泳ぐ、飛ぶ、およびカスタム移動モードをサポートしています。 基本的なキャラクター移動の仕組みや、アクタ コンポーネントの強力さを理解するために、自分で試してみることをお勧めします。
Parrot の場合、基本キャラクター移動コンポーネントは、デベロッパーが求めていたゲーム感覚をそのまま提供していません。 しかし、構築の基盤としてしっかりとしたベースを作りました。 UParrotCharacterMovementComponent C++ クラスは UCharacterMovementComponent から派生しています。 この移動コンポーネントは、BP_ParrotPlayerCharacter 内の CDO 移動コンポーネントに次のように設定できます。
では、Parrot 移動コンポーネントは実際に何をするのでしょうか。 簡単に言うと、このコンポーネントは、ベース移動コンポーネントのジャンプ関連機能をオーバーライドすることで、「プラットフォーム ゲーム風」のジャンプを定義できます。 設計調整可能な値をいくつか使用することで、ジャンプ発生時にプレイヤー キャラクターの重力スケールとジャンプ速度を変更し、一定時間内に頂点の高さに到達できるようにします。 頂点に到達したら、下降方向の重力スケールの適用を開始します。 プレイヤーがジャンプ入力を早く離した場合は、乗数を適用して重力をスケールアップできます。
その結果、Z 軸に衝撃を与えるだけのジャンプではなく、プラットフォーム ゲームで期待されるような「感覚」に近いジャンプが実現します。
基本キャラクター移動コンポーネントの高度な機能を活用することで、Parrot 移動コンポーネントのロジックをジャンプに集中させることができます。 移動コンポーネントの BP_ParrotPlayerCharacter のインスペクターにある値も確認することをお勧めします。これは、移動コンポーネントの各要素がどのように連携して動作するかの全体像を把握するのに役立ちます。 移動ロジックは、さまざまなユースケースに合わせて拡張できます。