情報は力ではない

UE4 とか Blender とか。

攻撃の当たり判定の実装方法

攻撃の当たり判定を実装したかったので、自分が行った実装方法を記述しておきます。

この記事で説明するのは次の動画のように、相手に攻撃して、ダメージを与えるところまでです。 わかりづらいですが、左上に与えたダメージを表示しています。


UE4 攻撃当たり判定処理

Unreal Engine
Version 4.19.2

攻撃の当たり判定の実装方法

攻撃の当たり判定の実装を Paragon の Shinbi を使って実装していきます。 理由は、Shinbi のアセットには、すでにコンボの実装が行われており、 あとは当たり判定のロジックを追加するだけで良いので、楽だからです。

実装をするにあたり、Third Person Template でプロジェクトを作成し、 マーケットプレイスから Paragon: Shinbi を入手して、プロジェクトに追加しておきます。

剣に Collision を追加する

まずはじめに Shinbi が持つ剣にコリジョンを追加します。

コンテンツブラウザから ShinbiPlayerCharacter を探し、開きます。 Components タブから Mesh を選択し、AddComponent ボタンを押して Box Collision を追加します。 名前は SwordCollision にしました。 SwordCollision を選択し、Details タブを見ると Parent Socket という項目があります。 ここに Socket を指定すると、SwordCollision がその Socket に追従するようになります。それでは、 SwordCollision に指定する Socket を探したいと思います。コンテンツブラウザから Shinbi_Skelton を探し、開きます。 weapon_r ボーンの下に Sword ソケットがあり、これが指定する Socket にちょうど良さそうです。

ShinbiPlayerCharacter に戻り、Components タブで SwordCollision を選択し、 Details タブの Parent Socket に Sword と入力します。虫眼鏡アイコンを追加して、検索するのが良いかと思います。 あとは、大きさと位置を調整します。今回はこのような感じにしました。

f:id:masahiro8080:20180526111836j:plain

ダメージ処理の実装

次に、相手にダメージを与える処理を実装していきます。

ShinbiPlayerCharacter の Event Graph を開き、右クリックを押し、Custom Event を追加します。 名前は AttackBegin/End としました(カウチナイトのサンプルから拝借しました)。実装は次の画像のようにしました。

f:id:masahiro8080:20180526122458p:plain

AttackBegin/End イベントは Attacking という bool 値を Input に持ちます。これは、攻撃中かどうかを表すフラグです。 Attacking が true の場合は、Box Collision の Collision を Enabled にし、当たり判定イベントを起こします。 false の場合は、No Collision にし、当たり判定イベントを起こさないようにします。 次に、SwordCollision の OnComponentBeginOverlap イベントを追加しています。 これは SwordCollision がオーバーラップした際に呼ばれます。SwordCollision の Collision Preset は何も指定していなければ OverlapAllDynamic となっているかと思います(Detail タブから確認できます)。 ですので、全てのオブジェクトとオーバーラップイベントを起こします。 オーバーラップした相手(OtherActor) が Self(自分自身) でない場合に Apply Damage ノードを使用して相手にダメージを与えるように実装しました。 SwordCollision は全てのオブジェクトをオーバーラップイベントを起こすので、自分自身ともオーバーラップイベントを起こしてしまいます。 ですので、自分自身とオーバーラップした際にはダメージ処理が走らないようにしています。 ApplyDamage ノードで指定する与えるダメージ(Base Damage)は固定でもよかったのですが、とりあえず関数化しておきました。 Base Damage 変数に乱数を足した値を返すような関数です。

f:id:masahiro8080:20180526122539p:plain

最後に、Begin Play イベントにも次のような処理を記述しておきます。 これは、初期状態では SwordCollision は Collision Enabled 状態なので、No Collision にし、攻撃時のみ Collision Enabled になるようにしています。

f:id:masahiro8080:20180526122711p:plain

ここまでで相手にダメージを与える処理ができました。

アニメーションからダメージ処理を呼ぶための実装

次に、攻撃アニメーションに合わせて先ほど実装した AttackBegin/End を呼ぶようにしたいと思います。 そのために、Shinbi の攻撃アニメーションを探します。 ShinbiPlayerCharacter の Event Graph に Combo System Setup とコメントされた箇所があり、ここに 3 つ Play Anim Montage があります。 この Play Anim Montage に設定されいる Animation Montage が攻撃のアニメーションであり、上から順に 1, 2, 3 コンボ目のアニメーションです。

f:id:masahiro8080:20180526122728p:plain

これらのアニメーションに当たり判定開始と終了を示す Notify を追加していきます。

1 コンボ目の Animation Montage である PrimaryMelee_B_Slow_Montage を開き、Notifies Area を見ます。 Notify Track を右クリックし、New Notify を押します。名前は AttackStart にします。 この追加した Notify を当たり判定開始のフレームに移動します。今回はだいたい 8 フレーム目に移動しました。 同様の手順で、名前が AttackEnd の Notify を 12 フレーム目に移動しました。

次に 2 コンボ目の Animation Montage である PrimaryMelee_C_Slow_Montage を開き、先ほどと同じように Notifies Area にある Notify Track を右クリックします。 一度作成した Notify は新規に作成する必要はなく、Custom 欄に追加されている AttackStart と AttackEnd を Notify Track に追加し、 当たり判定開始位置と終了位置にそれぞれ移動します。3 コンボ目の PrimaryMelee_D_Slow_Montage も同様の手順で Notify を追加します。

これで、アニメーションブループリントで当たり判定開始と終了を検知できるようになりました。

次に、Shinbi_AnimBlueprint の Event Graph を開きます。 Event Graph 上で右クリックし、Attack と入力すると、AnimNotify_AttackStart Event と AnimNotify_AttackEnd Event が公開されています。 これらのイベントはアニメーション再生時に、先ほど設定した AttackStart Notify や AttackEnd Notify のフレームを通過した際に呼び出されます。 Event Graph にこれら Event を配置し、図のようにノードを配置します。 Try Get Pawn Owner ノードでこの AnimInstance を設定している Pawn を取得し、ShinbiPlayerCharacter にキャストします。 その後、ShinbiPlayerCharacter で実装した Attack Begin/End ノードを呼び出します。当たり判定開始時は Attacking を true に、 当たり判定終了時は Attacking を false にしています。

f:id:masahiro8080:20180526122920p:plain

ここまでで Shinbi が攻撃アニメーションをすると剣に当たった敵にダメージを与えることができるようになりました。 次にダメージが敵に与えることができているかの確認をしていきます。

ダメージ処理の確認

まず、World Settings を開きます。Game Mode 欄にある、Default Pawn Class を ShinbiPlayerCharacter にします。 これで、ゲーム開始時のキャラクターが Shinbi になります。

f:id:masahiro8080:20180526123004j:plain

次に、敵となる Character を配置します。 コンテンツブラウザから ThirdPersonCharacter を探します。今回は、この Character を敵とします。 ThirdPersonCharacter の Event Graph を開き、右クリックを押し、Any Damage ノードを配置します。 このノードは Apply Damage 等でダメージを与えられた際に呼び出されます。 ダメージ処理の確認のために、Print String ノードでダメージを表示できるようにしておきます。 (Draw Debug String ノードを使ってもよかったのですが、4.19 では、Position に設定した場所に値が表示されないようです。)

f:id:masahiro8080:20180526123055p:plain

あとは、この ThirdPersonCharacter をマップに配置し、ゲームを開始します。 左クリックを押すことで Shinbi は攻撃できます。 配置した ThirdPersonCharacter に近づき、攻撃すると、左上に与えたダメージが表示されると思います。

これでダメージ処理の確認ができました。

終わりに

今回はこれで終わりですが、敵に HP を設定して、死を実装したり、ダメージを受けた際のヒットリアクションを追加したり、 攻撃が当たると同時に音を出してみたり、敵の HP バーを表示して残り HP が表示されるようにしたり、AI を実装して、敵との戦闘ができるようにしたりと 色々と拡張ができると思います。今回の説明がゲーム作成の助けになれば嬉しいです。

次の動画は、ダメージをくらうとヒットリアクションをし、HP が 0 になったら、敵が倒れる実装を追加してみたやつ。 この記事では、ヒットリアクションと倒れる機能まで説明しなかったので、そのうちちゃんと説明したい。