5.21.2014

UE4 におけるダメージ機能

作成 Jeff Farris

「人に危害を加えざるを得ない場合は、報復の恐れが必要ないくらい徹底的にやるべきである」- マキャベリ

「ダメージ」はゲームでは一般的なコンセプトです。そこで今回は、UE4 のゲームフレームワークに含まれているダメージ機能について簡単に解説したいと思います。

ダメージは、ベースの Actor クラスの機能であるため幅広く使用できます。結果が早くほしい場合は、一般的な機能に簡単にアクセスできます。必要に応じて独自のダメージモデルをカスタマイズできる拡張性もあります。また、ダメージに対する反応のしかたは想定されていません。だから、エンジンには「ヒットポイント」とか「戦闘不能」という概念がありません。これらの概念は、普通、ゲームそれぞれで固有のものであるからです。それらを一般化しても、かえって苦労をかけることになると考えたのです。

基本的なダメージのコンセプト

ダメージには、よく使われるコンセプトがいくつかありますので、簡単に紹介してみましょう。

DamageType

その名の通り DamageType は、ダメージ源とは無関係にダメージの「型」を記述できるオブジェクトです。これが役立つのは、ダメージのソースが多数あり、それらに共通の機能を持たせたい場合です。

簡単な例を使って説明しましょう。火のダメージがあるとします。キャラクターがそのダメージを受けると、「あっちー」と叫んで、近くの水のあるところまで駆け込ませるようします。その場合、キャラクターにやけどをさせることができるあらゆるアクタ (または、やけどを負う可能性があるあらゆる型のアクタ) にこのコードをコピーするよりも、火のためにダメージ型 (UDamageTypeFire) を定義して、そこに何らかの HandleDamagedCharacter() 関数を備え、適宜 TakeDamage() の呼び出しチェーンからその関数を呼び出すようにするのがよいでしょう。

Instigator

Instigator とは、ダメージを引き起こすです。普通は、PlayerController や AIController が Instigator となります。火のダメージの場合は、プレイヤーか、火をつける AI がこれになるでしょう。

DamageCauser

causer とは、普通、ダメージを引き起こすのことです。たとえば、ACampFire アクタの上を歩くと、それが causer となります。

C++ におけるダメージ

まず、ネーティブコードがダメージにどのように対応しているか見て行上できましょう。

この例の場合は、アクタにダメージを与えるのは簡単です。そのアクタ上で TakeDamage() を呼び出すだけです。

virtual float TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, class AController* EventInstigator, class AActor* DamageCauser);

また、ダメージに対して反応させるためには、ダメージを受けたアクタ上で TakeDamage() をオーバライドして、カスタムの操作を挿入するだけです。簡単ですよね!

ご覧のとおり、TakeDamage() のコールでは、引数として DamageEvent が渡されていますね。この FDamageEvent データ構造体には、ダメージを発生させるイベントの特定の状況に関するデータが含まれています。それによって、反応のためのコードが適切に対応できるようになります。UE4 には、次のような 3 種類の味のダメージ イベントがビルトインされています。

FPointDamageEvent

「その方向からうたれたため、顔のここが痛い」

ポイント ダメージ イベントは、被害者の特定の点に加えられたダメージ (弾丸やパンチなど) を具現化しています。このイベントには、攻撃が到来した方向と、サーフェスのインパクトを記述する FHitResult が含まれています。

FRadialDamageEvent

「あの大きな爆発のせいで、左半身全体が痛い」

ラジアル ダメージ イベントは、ある 1 点を源とする放射状のダメージを具現化したものです。代表的な例としては、爆発からダメージがあります。このダメージには、爆心地、および、空間におけるダメージの減衰を記述するためのデータ、影響を受けるコンポーネントのリストが含まれています。

FDamageEvent

「あ痛っ」

もっとも汎用的なダメージ モデルです。含まれているものは、オプションの DamageTypeClass だけです。

これらのビルトインされているイベントの型が、求めているものではない場合は、独自の構造体を FDamageEvent から派生させ、必要なデータを格納することができます。

ブループリントにおけるダメージ

ブループリントでダメージを扱う場合も同様です。ただし、ダメージの適用とダメージへの反応が、イベントの型によって用意されている点が異なります。ダメージを与える場合は、グローバルにアクセスできるノードが利用できます。ApplyDamage、ApplyPointDamage、ApplyRadialDamage などがそれです。ダメージ イベントに反応するためには、同様の took damage (ダメージを受けた) イベント群が用意されています。これらはアクタ クラスとレベル内のアクタ インスタンス両方のためのものです。

ご自分のプロジェクトのためにカスタムのダメージ イベントを定義した場合は、おそらく、ブループリントで使用するために、同様の関数およびデリゲートの集まりをエクスポーズする必要が出てくるでしょう。

さあ、ダメージを楽しんでください!そして、ダメージに関する質問や体験談などがありましたら、フォーラムをお訪ねください!

最近の投稿

UNREAL FEST EAST 2018 参加登録開始!公式サイトを公開しました

10月14日(日)に横浜にて開催される『 UNREAL FEST EAST 2018 』の参加登録を開始しました。

The Mill と Monster.com が生み出したモンスターをアンリアル エンジンが操る

高い評価を受けているスタジオ、The Mill は、毛皮に覆われた巨大なクリーチャーが登場するアニメーション スポットをいくつも短期間で制作する必要に...

FOX Sports の 2018 FIFA ワールドカップ放送で Drive Studio はアンリアルを活用

Drive Studio は FOX Sports の 2018 FIFA ワールドカップ放送でアンリアル エンジンを活用し、環境、インタースティシャ...