
【レビュー】UE4 Destruction System のブループリントを見る
お疲れさまです。UE4の10月無料コンテンツ「Destruction System」のブループリントについて、勉強がてら内部を覗いてみました。
他の記事を書きながらなのでザックリとではありますが、
まとめておこうと思います。
難易度:初級?(Actor内で処理が完結するのでわかりやすい)
アセット概要
破壊されたように表現するアセット。ベースアクタ「B_DestructionSystemActor」を継承して設定を作成していくようです。
内容としてはダメージを与えると、メッシュを変更する仕組み(Apply Damageが起点)
設定された各ステップごとにダメージを換算して、
ステップ1(ダメージ100で次ステップへ)
→ステップ2(ダメージ123で次ステップへ)
→ステップ3(最終段階・全壊状態)
というように、破壊状態を遷移していくような仕組みでした。
アニメーションが使えない環境や動きを出しすぎたくないゲームデザインなどに向いていそうですね。
ステップの変数配列 States
「States」として各状態を管理しているようです。
アクタ内で配列化して使うようですね。
各状態の名前とメッシュ、パーティクル、サウンド、壊すために必要なダメージ量(HP)を設定する項目がありました。この状態が終わったら、その下に「Devrus Actor Properties Array」設定をもとに、破片をSpawnするようです。要素を足したいときはこの構造体に要素を足せばよさそうです。
破片の変数配列 DebrisActorPropertiesArray
破壊されたときの破片の設定ですね。
こちらも要素を追加するのは簡単そうです。
DebrisMesh:破片メッシュ
SpawnOffset:破片の初期位置オフセット
SpawnImpluse:破片が飛び散る力の量
DestroyDelay:破片が消えるまでの時間
bPhysicsEnabled::破片のPhysicsをONにするか
bCollisionEnabled:破片のコリジョン
bCastShadows:破片の影設定
基本的に必要な項目は揃っていますね!
Construction Script
Construction Script上では、設定の確認と反映を行っていました。
State配列の長さが0ならSate変数を-1、それ以外なら指定したStarting値をClampチェックして、Starting State変数に格納。
で、State配列をFor each Loop。「Clamp State Value」関数で各要素につけられたステート名をチェックしたあと、CurrentHP変数に総HPを格納しています。
For each Loop終了後は「Get State HP」関数でState配列から、StateごとのHPの値を取得、そして「Calculate Starting HP」関数に渡しています。
ここでHPが破綻していないかなどを確認して返し、現StateのHPとして管理する変数(StartingHP、CurrentStateHP、LastCSSStartingHP)に格納しています。最後の「Go to State」関数ではState配列から初期メッシュやパーティクル、サウンドを設定していました。
イベントグラフ
Any Damageイベントで状態を管理していました。
Current HPを減算して、ダメージにより総HPが0以下になれば「Begin Death」関数を、総HPが1以上残ったなら「Calculate Next State」関数で計算しています。
Calculate Next State 関数
While Loop内で現StateのHPとダメージを比較してダメージが現StateHP以内ならStateHPを返してすぐにループを抜け、残りHPと現Stateを 戻り値にします。
ダメージが現StateHPを上回っていたら残りダメージを保存して、Stateをインクリメント。それを引数にして「Get State HP」関数から次のStateのHPを取得して再度Loopを走らせている。
そしてHPを減算しきったら返す、という形。わかりやすいです。
普段あまり使わない処理の仕方で参考になりました。
関数から出たら戻り値を変数に再度格納して、「Go to State」関数でStateを変更、「Go to State」関数ではメッシュ、パーティクル、サウンドを再度設定しています。
Stateが3段階あった場合、ダメージによっては1段階目から3段階目まで一足飛びで遷移しますので、設定するメッシュは飛んだとしても違和感ないものが良さそうです。
まあバランス次第でどうにでもなりそうではありますが……
そうそう、この関数を抜けたあと、(次Stateに移行するか否か関係なく)必ず「Go to State」関数が実行されるんですが、ダメージがStateHP範囲内でも、「Set Static Mesh」などのセット処理が実行されるのはどうなのかな? と思いました。Stateが変わったときだけセットし直せばいいのでは、と(試していません)。
パーティクルやサウンドも遷移時ではなくダメージが与えられるたびに再生されるので、遷移タイミングで音を鳴らしたい・変えたいというときは別途処理が必要そうです。
BeginDeath 関数
総HPが0以下なら実行される処理。
「MakeLastStatePermanent」変数がTrueならメッシュが最後の状態で残ります。それ以外ならアクタをHiddenしてCollisionを消し、パーティクル・サウンドを再生。
その後「DebrisActorsTimersHandles」配列に破片の登録があれば「Spawn Debris Actor」関数でアクタをSpawnしています。
壊れたときにポップするような処理を入れるなら、このあたりから派生するのが良いんでしょうか?
Spawn Debris Actor 関数
Actor をSpawnして破片の DebrisActorPropertiesArray 配列から情報を取り出してセッティング。Random Vector in Range マクロでは最小値と最大値でランダム数を取り出しています。
ランダム数に「Snap to Grid」をしているのは何故だろう?
各プロパティのセッティングは「Set Debris Actor Preperties」関数で行っています。
「Set Debris Actor Properties」関数では残りActorの削除も適切に行われていました。Timerで行われています(Destory Actorを呼ぶ)。管理的に楽で良さそうですね。Timer大好きです。
このActor自体の削除管理はTimerが使われています。
「Begin Death」関数のこの部分ですね。
デフォ0.1秒で破片がDestroyされているか確認して、すべての破片が無くなったら自身を削除するようになっています。親切設計ですね。
終わり
以上、「Destruction System」の中身レビューでした。
破壊の仕組みというより、メッシュを状態遷移させる仕組みと言える気がします。個人的にはダメージ管理のループと、破片の管理部分が参考になりました。レベルデザイナーやプランナーでも扱いきれる簡単で良い仕組みだと思います!(とはいえイチから作るのは面倒ですが)
拡張しやすそうですし、独特の演出が入れられますので、RPGやアドベンチャー系の破壊オブジェクトを作るときなどには役立つのではないでしょうか。
では!