16.1K Views
October 28, 19
スライド概要
発表者: 林耕司さま(株式会社ユークス)
本スライドは2019年9月20日に行われた勉強会「 UE4を用いたTPS制作事例 ?Earth Defense Force: Iron Rainの場合?」の講演資料となります。ユークス様、このような貴重な情報を一般に公開していただきまことにありがとうございます!
※講演資料内にGif動画などが埋め込まれてる可能性がございます。以下のリンクからオリジナルのスライドをご参照していただくことをおすすめいたします。
https://epicgames.box.com/s/nynlfef4ppdsli7ghtmof35z7a38s5xk
ダウンロードのためのパスワードは "EDFIREpic"です。
Unreal Engineを開発・提供しているエピック ゲームズ ジャパンによる公式アカウントです。 勉強会や配信などで行った講演資料を公開しています。 公式サイトはこちら https://www.unrealengine.com/ja/
UE4を用いたTPS制作事例 EDF:IR 地球を衛る兵士の作り方 EDF:IRのキャラクター制御 株式会社ユークス リードプログラマー 林 耕司 ©2019 YUKE'S ©2019 D3 PUBLISHER
はじめに ・4.19.2がリリースバージョンです ・本日お話する内容が、先日リリースされた4.23でも同じ動作をするかは 保証できませんのでご了承ください ・参考情報程度ですが、開発期間中に4.20.2までは動作確認しました ・原則としてエンジンは改造していません。必要最低限のバグ修正やCLの 取り込み、一部エディタの機能調整のみ施しました ©2019 YUKE'S ©2019 D3 PUBLISHER
今日お話しすること 1.キャラクター関連クラス構造 2.コンポーネント 3.ステート制御 4.物理(ラグドール)制御 5.キーコンフィグ 6.最適化 ©2019 YUKE'S ©2019 D3 PUBLISHER
今日お話しすること 1.キャラクター関連クラス構造 2.コンポーネント 3.ステート制御 4.物理(ラグドール)制御 5.キーコンフィグ 6.最適化 ©2019 YUKE'S ©2019 D3 PUBLISHER
キャラクター関連クラス構造 yJetLifter Actor yJetLifter Pawn yPawn yCharacter ySoldier yEnemy yVehicle yInsect yBesal yTank BP_Besal BP_Tank yTrooper yJetLifter BP_StormAnt BP_Trooper BP_JetLifter BP_CrazyAnt ©2019 YUKE'S ©2019 D3 PUBLISHER
キャラクター関連クラス構造 Actor yJetLifter yJetLifter Pawn yPawn { yCombatInterface、yControllerInterface、yPhysicsInterface、yAnimStateInterface } [ yCombatComponent ] yCharacter yEnemy yVehicle [ yCharacterMovementComponent ] [ yEnemyMovementComponent ] ySoldier yInsect yBesal yTank [ yWeaponComponent ] yTrooper yJetLifter BP_StormAnt BP_Trooper BP_JetLifter BP_CrazyAnt BP_Besal BP_Tank ©2019 YUKE'S ©2019 D3 PUBLISHER
今日お話しすること 1.キャラクター関連クラス構造 2.コンポーネント 3.ステート制御 4.物理(ラグドール)制御 5.キーコンフィグ 6.最適化 ©2019 YUKE'S ©2019 D3 PUBLISHER
コンポーネント 作成したコンポーネント達(★のコンポーネントを説明します) ★コンバットコンポーネント ・エナジーコンポーネント ★武器コンポーネント ・投擲コンポーネント ・移動コンポーネント ・ヘッドライトコンポーネント ・IKコンポーネント ・ラジアルブラーコンポーネント etc.. ©2019 YUKE'S ©2019 D3 PUBLISHER
コンバットコンポーネント yCombatComponentクラス キャラクターが攻撃(yStrike)を受けた際の、ダメージ関連処理を行い ます。具体的にはダメージ量計算・蓄積、状態異常、死亡判定など。 yPawnが継承しているyCombatInterfaceクラスを経由して、 被弾時のヒットリアクションのステート遷移等のリクエスト処理も行います。 ©2019 YUKE'S ©2019 D3 PUBLISHER
コンバットコンポーネント このコンポーネントにキャラクターのダメージ処理を統一する事で、 各作業者が同じ処理を把握している状態になり、作業負担を分散する ことが出来ました。 また、特定のキャラクターに依存する処理をなくす事でキャラの種類が 増えたときも容易に対応出来ました。 例えば右図のセントリーガン等のような 自立型のアイテムなどがそうです。 ©2019 YUKE'S ©2019 D3 PUBLISHER
コンバットコンポーネント yStrike 攻撃がヒット yPawn yCombatComponent TakeDamage ダメージ計算 ヒットポイント更新 死亡処理 死亡判定 ヒットリアクション更新 リアクション判定 ©2019 YUKE'S ©2019 D3 PUBLISHER
コンバットコンポーネント yCombatComponentのダメージ処理でやっている細かい処理 ● FDamageEvent構造体からダメージパラメータを取得して保持 ● 無敵等、被ダメージモードでダメージ処理の分岐条件を決定 ● 難易度、防御力、属性、耐性などを考慮したダメージ量の計算 ● 状態異常値の蓄積と更新、 yCombatInterfaceを経由して 状態異常の実行(実装はyPawnの派生クラス) ©2019 YUKE'S ©2019 D3 PUBLISHER
コンバットコンポーネント yCombatComponentのダメージ処理でやっている細かい処理 ● ダメージ量(回復量)によるヒットポイント更新 ● 死亡判定、死亡時は死亡処理の実行(実装はyPawnの派生クラス) ● 死亡していない場合は適用するヒットリアクションを決定(攻撃パラメー タをベースに重量差を考慮してヒットリアクションを決めます) ©2019 YUKE'S ©2019 D3 PUBLISHER
武器コンポーネント yWeaponComponentクラス 汎用的な武器の機能を提供するコンポーネントクラスです。 主に発射トリガー(引き金)の制御、yStrikeの発射(スポーン)、 弾数計算、発射間隔のカウント、リロードなどの制御を行います。 これらの制御に関しては全て武器パラメータとして外部化されています。 特殊な制御を除いて、全てパラメータで制御できます。 ©2019 YUKE'S ©2019 D3 PUBLISHER
武器コンポーネント 武器コンポーネントは汎用的な実装となっているため、ソルジャーが扱う 銃器類などの独立した実体を持つ武器以外に、エネミーやビークルの様 な自身を武器とするような攻撃も、この武器コンポーネントを使用して対 応しています。 ©2019 YUKE'S ©2019 D3 PUBLISHER
武器コンポーネント アサルトライフルなどのソルジャーの武器は、yWeaponActorクラスに 武器メッシュと武器コンポーネントを持たせており、メッシュとコンポーネント を関連付けて、銃口からyStrikeが発射される様にしています。 yWeaponActor(トリガー制御) Skeletal Mesh yWeaponComponent(武器機能) ©2019 YUKE'S ©2019 D3 PUBLISHER
武器コンポーネント エネミーやビークルには独立した武器はないので、エネミーやビークルの メッシュを武器メッシュとして武器コンポーネントに登録しています。 例えば右図のような射撃武器(蟻酸)なら、アリのメッシュに発射口と なるソケットがあり、そこからyStrikeを発射しています。 ©2019 YUKE'S ©2019 D3 PUBLISHER
武器コンポーネント 武器コンポーネントから攻撃が発生してダメージに至る流れ 1.武器のトリガーが引かれる 2.武器からyStrikeがスポーンされる 3.yStrikeはトレースで当たり判定を取る 4.トレースにヒットしたら着弾判定を行う 5.着弾したならダメージを発生させる(ApplyDamage) 6.着弾時は貫通判定を行い、貫通しないならyStrikeを破棄 ©2019 YUKE'S ©2019 D3 PUBLISHER
武器コンポーネント 武器コンポーネントのバリエーション ● チャージ武器コンポーネント ● ロックサイト武器コンポーネント ● ワイヤー武器コンポーネント ● 投擲武器コンポーネント ● サテライト武器コンポーネント などなど 通常 ワイヤー チャージ 投擲 ロックサイト サテライト ©2019 YUKE'S ©2019 D3 PUBLISHER
今日お話しすること 1.キャラクター関連クラス構造 2.コンポーネント 3.ステート制御 4.物理(ラグドール)制御 5.キーコンフィグ 6.最適化 ©2019 YUKE'S ©2019 D3 PUBLISHER
ステート制御 開発初期のステート制御はTick、InputEvent、AnimNotify、 TakeDamageなどバラバラのタイミングで行っていましたが、アクション が多くなるにつれてステート制御に隙間が生まれてしまい、ステート遷移 がうまく行われない不具合が多発してしまいました。 スプリント停止を繰り返す Eダッジと着地の遷移が衝突 回復中にダメージを受ける ©2019 YUKE'S ©2019 D3 PUBLISHER
ステート制御 コントローラーの 入力イベント ダメージによる ヒットリアクション ダウン! Tick内の ステート制御 アイテム使う! ジャンプ! 着地した! ABPイベントによる ステート設定 モーション終わり! AnimNotifyによる ステート設定 ©2019 YUKE'S ©2019 D3 PUBLISHER
ステート制御 その為、各イベントではアクションを実行するためのリクエストを発行して その時点からTickを有効化、実際のステートの遷移判定、制御、更新を Tick処理中に行う形に統一しました。そして全ての処理が終わりリクエス トが無くなればTickを再度無効化します。 (ソルジャー、エネミー共に多少構造は異なりますが、基本的には同様の 制御にしています) ©2019 YUKE'S ©2019 D3 PUBLISHER
ステート制御 コントローラーの 入力イベント ジャンプ! ダメージによる ヒットリアクション ダウン! ABPイベントによる ステート設定 着地した! アイテム使う! AnimNotifyによる ステート設定 Tick内の ステート制御 ステート遷移処理が 各フラグの状態をみ て、適切なステート を選択します。 ダウン! 必要に応じて各フラ グの状態から、キャ ンセル処理等を行い ます(例:アイテムの 使用を中断する処理) モーション終わり! ©2019 YUKE'S ©2019 D3 PUBLISHER
ステート制御 このC++側のステート制御の変更に伴い、今までABP側でもステート 遷移条件にC++側のステート以外のパラメータを使用していたところを、 C++側のステートと同期する様にABP側のステート遷移が行われるよう に変更しました。 この時必要に応じて、C++側のステートも追加しました。 ©2019 YUKE'S ©2019 D3 PUBLISHER
ステート制御 コントローラーから入力イベントが呼ばれた場合はアクションフラグを設定。 Tick処理中に実装したステート更新処理内でフラグを参照し、適切なス テートへの遷移を行いました。 ジャンプボタン入力 入力イベント処理内で IsInputJumpフラグ立つ ジャンプにステート遷移 ABPのステートも遷移! ©2019 YUKE'S ©2019 D3 PUBLISHER
ステート制御 ストライク処理からダメージイベントが呼ばれた場合も同様にヒットリアク ションの遷移リクエスト値を設定して、Tick処理中にヒットリアクション更 新処理から適切なステートへの遷移を行いました。 攻撃がヒット! ヒットリアクションを ダウンに書き換える! ダウンにステート遷移 ABPもステート遷移! ©2019 YUKE'S ©2019 D3 PUBLISHER
ステート制御 戦闘不能も同様です。コンバットコンポーネントで死亡処理が呼び出され たあとで、Tick処理中のステート更新処理で更新を行っています。 攻撃がヒット! 体力が0なので死亡 死亡フラグが立つ! 戦闘不能にステート遷移 ABPのステートも遷移! ©2019 YUKE'S ©2019 D3 PUBLISHER
ステート制御 アニメーションからAnimNotifyで状態制御フラグの設定があった場合 も、Tick処理中にステート更新処理でフラグを参照しステートを制御して いました。また、AnimNotify以外の通知処理をAnimNotifyに統合 しました。 AnimNotifyの使用範囲を把握するためです。 着地モーションの終了 タイミングにAnimNotify AnimNotifyからの設定により モーション終了フラグが立つ 待機ステートに遷移! ABPのステートも遷移 ©2019 YUKE'S ©2019 D3 PUBLISHER
今日お話しすること 1.キャラクター関連クラス構造 2.コンポーネント 3.ステート制御 4.物理(ラグドール)制御 5.キーコンフィグ 6.最適化 ©2019 YUKE'S ©2019 D3 PUBLISHER
物理(ラグドール)制御 爆発など大きな衝撃を伴うダメージを 受けるとソルジャーやエネミーは 吹っ飛びリアクションのステートに 遷移します。 その間はラグドール状態となり、 死亡しなければ起き上がります。 ©2019 YUKE'S ©2019 D3 PUBLISHER
物理(ラグドール)制御 以下の流れでラグドール状態の制御を行っています。 1.衝撃ダメージ ⇨ ヒットリアクション ⇨ ラグドール開始 ⇨ 2.アクタ位置の更新 ⇨ ラグドール終了判定 ⇨ 3.最終姿勢から再生するアニメーションを判断 ⇨ スナップショット ⇨ 4.移動制御への速度引き継ぎ ⇨ ラグドール終了 ⇨ 5.スナップショットから姿勢へのブレンド ⇨ 起き上がる ©2019 YUKE'S ©2019 D3 PUBLISHER
物理(ラグドール)制御 1.衝撃ダメージ ⇨ ヒットリアクション ⇨ ラグドール開始 爆発などのダメージによって衝撃が発生し、「吹っ飛び」のヒットリアクショ ンをリクエストします。リクエストを受けてステートを吹っ飛びに遷移させま す。吹っ飛びステートのアニメーション側からラグドール開始の AnimNotifyが呼ばれラグドール状態のリクエストが出ます。 Tickがリクエストを受けて、メッシュのPhysics Assetをラグドール用に 変更し、物理シミュレーションを有効にします。 ©2019 YUKE'S ©2019 D3 PUBLISHER
物理(ラグドール)制御 1.衝撃ダメージ ⇨ ヒットリアクション ⇨ ラグドール開始 衝撃ダメージと ヒットリアクション Physics Assetsをラグドール用に変更 ラグドールを開始 ©2019 YUKE'S ©2019 D3 PUBLISHER
物理(ラグドール)制御 2.アクタ位置の更新 ⇨ ラグドール終了判定 ソルジャーやエネミーはカプセルコンポーネントをルートコンポーネントとして いるため、ラグドール状態の時はメッシュの位置に合わせてカプセルを移 動する必要があります。 特にプレイヤーが操作しているソルジャーはカメラを追従させる必要があ り、毎Tick位置更新を行っていました。 ©2019 YUKE'S ©2019 D3 PUBLISHER
物理(ラグドール)制御 2.アクタ位置の更新 ⇨ ラグドール終了判定 位置更新はシンプルです。 メッシュの基準となるボーン位置を取得して、 その少し上の位置にSetActorLocationで カプセルコンポーネントを移動しています。 ©2019 YUKE'S ©2019 D3 PUBLISHER
物理(ラグドール)制御 2.アクタ位置の更新 ⇨ ラグドール終了判定 終了判定はアクタ位置移動後に下方向にライントレースを出して接地判 定を行います。以下の3つの条件で接地したかどうかを判断しています。 ・トレースが地形等にヒットしているか ・現在の移動速度が一定速度以下か ・上2つの状態が一定時間継続したか ©2019 YUKE'S ©2019 D3 PUBLISHER
物理(ラグドール)制御 3.最終姿勢から再生するアニメーションを判断 ⇨ スナップショット ラグドール終了判定にヒットしたなら、ダウンステートに遷移する為の情報 を取得します。ソルジャーはメッシュの向きからうつ伏せかどうかと、カメラ 向きとメッシュの向きから起き上がりステートで使用するモーションを取得 します。エネミーにはカメラがないので、うつ伏せか仰向けかの情報のみを 取得します。 ©2019 YUKE'S ©2019 D3 PUBLISHER
物理(ラグドール)制御 3.最終姿勢から再生するアニメーションを判断 ⇨ スナップショット 姿勢の情報を取得したら、スナップショットの作成を行います。 スナップショットとは、今のメッシュのポーズを保存しておいて、後から 使えるようにする機能です。 ©2019 YUKE'S ©2019 D3 PUBLISHER
物理(ラグドール)制御 3.最終姿勢から再生するアニメーションを判断 ⇨ スナップショット スナップショットの作成には2フレームかかるので、その間はまだ ラグドール状態です。スナップショットからダウンステートの姿勢に スムーズにブレンドするために、スナップショット作成時には次の ダウンステートに遷移しておきます。 ©2019 YUKE'S ©2019 D3 PUBLISHER
物理(ラグドール)制御 4.移動制御への速度引き継ぎ ⇨ ラグドール終了 スナップショットの作成が終われば、物理シミュレーションを終了してダウン ステートのアニメーションとスナップショットのブレンドを開始します。 この時まだ物理によるベロシティが残っていますので、これをムーブメントコ ンポーネントに引き継ぎます。こうすることで地上を滑りながらダウン姿勢 に遷移することができます。 ©2019 YUKE'S ©2019 D3 PUBLISHER
物理(ラグドール)制御 5.スナップショットから姿勢へのブレンド ⇨ 起き上がる スナップショットからダウンモーションへのブレンドが終了し、移動も停止し たなら、起き上がりステートに遷移します。 立ち上がったら起き上がりステートは終了し、待機ステートに戻ります。 ©2019 YUKE'S ©2019 D3 PUBLISHER
物理(ラグドール)制御 ラグドール中の位置更新や復帰は、以下の動画が参考になります。 Unreal Japan Stream | ポーズスナップショットでラグドール回避アニメーション https://youtu.be/1hP_QHsYMfw ©2019 YUKE'S ©2019 D3 PUBLISHER
今日お話しすること 1.キャラクター関連クラス構造 2.コンポーネント 3.ステート制御 4.物理(ラグドール)制御 5.キーコンフィグ 6.最適化 ©2019 YUKE'S ©2019 D3 PUBLISHER
キーコンフィグ EDF:IRでは1プレイヤーに複数のキーコンフィグ設定がありました。 ソルジャー、ビークル、ジライヤと操作対象毎の設定があり、画面分割 プレイ時には2プレイヤー分の設定を別々に行う必要がありました。 ©2019 YUKE'S ©2019 D3 PUBLISHER
キーコンフィグ まずはグーグル先生で検索するとすぐに見つかる方法に習って組んで みたのですが、切り替わりはするのですが画面分割プレイ時に問題が 出ました。 1P側の操作を変えると、2P側の操作も変わってしまうのです。 ©2019 YUKE'S ©2019 D3 PUBLISHER
キーコンフィグ これは紹介されていた方法ではプロジェクトのデフォルト設定を書き換えて 全体に反映する処理が動いていたためで、この方法では1Pと2Pを 別々の設定にすることは出来ませんでした。 ©2019 YUKE'S ©2019 D3 PUBLISHER
キーコンフィグ 解決方法としては、プロジェクトのデフォルト設定は書き換えずに、 各PlayerControllerがもつPlayerInputの情報を直接書き換えて 対応しました。 ©2019 YUKE'S ©2019 D3 PUBLISHER
今日お話しすること 1.キャラクター関連クラス構造 2.コンポーネント 3.ステート制御 4.物理(ラグドール)制御 5.キーコンフィグ 6.最適化 ©2019 YUKE'S ©2019 D3 PUBLISHER
最適化 キャラクターのCPU負荷対策で効果のあったものを簡単に紹介します。 ・URO ・Anim Instance ・Fast Pass ©2019 YUKE'S ©2019 D3 PUBLISHER
最適化 URO(Update Rate Optimization) アリなどの沢山出現するエネミーとNPCソルジャーに適用し、 CPU負荷を大きく減らすことが出来ました。ブループリントで 設定できるようにして、アニメーターが調整しました。 ©2019 YUKE'S ©2019 D3 PUBLISHER
最適化 URO 適用後の拡大図 ⇨ 赤:間引きなし 緑:1フレ間引き 青:2フレ間引き 黒:3フレ間引き ©2019 YUKE'S ©2019 D3 PUBLISHER
最適化 Anim Instance ABPの親クラスをC++側に実装し、 イベントグラフで行われていた変数を 更新する処理などをC++側で行う ように変更しました。CPU負荷を 大きく減らすことが出来ました。 ©2019 YUKE'S ©2019 D3 PUBLISHER
最適化 Fast Pass Anim Instanceの最適化の後で、Fast Pass対応も進めました。 アニムグラフも関数呼び出しや計算が多くありましたので、それらの 処理をC++側で行い結果の値だけを参照しています。 ©2019 YUKE'S ©2019 D3 PUBLISHER
質疑応答 Q:ラグドール中のオンライン同期はどうしていたのか? A:ラグドール中は同期していません。ラグドールの開始と終了を、RPC で同期するようにして、開始時に物理ボディの与えられる衝撃力と、終了 時の位置合わせだけは行っています。 ©2019 YUKE'S ©2019 D3 PUBLISHER
質疑応答 Q:UROで軽減される負荷は、アニメーション更新のTickだけか? A:基本的にはアニメーション更新のTickです。ただ、設定などの条件 次第ではTick以外の更新や評価もスキップするみたいです。 ©2019 YUKE'S ©2019 D3 PUBLISHER
質疑応答 Q:UROとAnimation Budget Allocatorの違いは? A:ザックリ言いますと、UROはカメラとの距離でTick頻度を調整します が、 Animation Budget AllocatorはCPU負荷によってTick頻度 を調整します。詳しくは公式ドキュメントを御覧ください。 https://docs.unrealengine.com/ja/Engine/Animation/AnimationBudgetAllocator/index.html ©2019 YUKE'S ©2019 D3 PUBLISHER
質疑応答 Q:エンジン更新時に問題は起きなかったか? A:起きませんでした。 必要以上にエンジン改造を行わない基本方針の元作業を進めていた事 が功を奏したのか、エンジン更新による影響はありませんでした。 ©2019 YUKE'S ©2019 D3 PUBLISHER
質疑応答 Q:画面分割プレイで、キーコンフィグ以外に起きた問題は? A:大した問題は起きませんでしたが、HUDとして使用したウィジェットの レイアウトがズレる問題と、カメラの情報を使用した射撃位置の計算、例 えばロックオンしたエネミーに向かって飛ぶミサイルの着弾位置などがズレ る問題が発生しました。 ©2019 YUKE'S ©2019 D3 PUBLISHER
ご清聴ありがとうございました! ©2019 YUKE'S ©2019 D3 PUBLISHER