57.ダメージを与える火を実装する
😺今回はコリジョン実践編として、プレイヤーにHPを実装して火に触れるとダメージを受けるという処理を実装していきます。
今回実装する機能↓
https://youtu.be/54-CBeB_RFE
火を作成して、その火に触れると(範囲内に行くと)HPが減って、HPが0になるとプレイヤーが倒れるモーションをするという事を実装していきます。
①火のブループリントクラス作成する
まずは火から作成していきます。
今回もサードパーソンテンプレートで、スターターコンテンツを使用します。
ブループリントクラス > アクタを作成します。名前をBP_Fireにします。
https://scrapbox.io/files/65c87711c8454d002415912d.jpg
開いたら追加からParticleSystemを追加します。
https://scrapbox.io/files/65c8772429e4c70026ccc301.jpg
ParticleSystemとは?
このParticleSystemコンポーネントでパーティクル(エフェクト)表示させる事ができます。例えば魔法や火や土埃などはパーティクルになります。パーティクルはエフェクトと同じ意味と認識してもらって構いませんがゲーム開発では一般的にパーティクルと呼ばれます。
🐱UnrealEngine内でパーティクルは1から作成する事ができますが、今回は既に用意されている火のパーティクルを使用していきます。
ParticleSystemを選択した状態で、パーティクルから「P_Fire」を選択します。
https://scrapbox.io/files/65c879be6ad0eb002478740b.jpg
さらに火のダメージ範囲となるコリジョンを追加します。追加からSphereCollisionを追加します。
https://scrapbox.io/files/65c879d4c22710002413587b.jpg
SphereCollisionを拡大縮小からXYZを全て2にします。
https://scrapbox.io/files/65c893a6afcbab0025afb8c2.jpg
🐱では今回はOverlap系のノードを使用していくので発動条件のコリジョン設定を確認していきましょう。
GenerateOverlapEventsにチェックが入っている事を確認して、コリジョンプリセットはOverlapAllにしておきます。(デフォルトのOverlapAllDynamicでも問題ありませんがわかりやすくOverlapAllにしておきました。)
https://scrapbox.io/files/65c893c76feeef0026ecd448.jpg
BP_Fireをレベルに配置します。
https://scrapbox.io/files/65c8940b84be9500257e90c8.jpg
一旦プレイして確認してみましょう。プレイヤーは火のコリジョンとは衝突せずに重なりを検知する設定になっているのが確認できます。
https://scrapbox.io/files/65c89428718f5b002520398a.gif
😺一方のアクタをオーバーラップの設定にすれば衝突はしなくなり、Overlap系のノードで重なりを検知できるようになるという事になります。
②火のダメージ範囲に入っているかどうかを判別する
ではここから火のコリジョン範囲内にプレイヤーが入った時にダメージを与えるという処理を作っていきます。
BP_Fireのイベントグラフを開きます。
https://scrapbox.io/files/65c894bf583acf00247e53e3.jpg
ノードを作るのはプレイヤー側か火側のブループリントクラスどっち?
前回のページ「アイテムを拾う機能を実装する」ではプレイヤー側にコリジョンのイベント処理を記載しました。今回はプレイヤー側ではなくレベル上のアクタとなる火のブループリントクラス側にノードを記載していきます。では、ノードを作る場所の判断基準は何なのでしょうか?明確な基準はありませんが"わかりやすい場所"を基準にノードを作る場所を決定しましょう。例えば前回のプレイヤーがコインを拾うという機能は"プレイヤー"が何かを行う側なのでプレイヤー側に処理を実装しました。
つまり処理を行う主格側に処理を実装していく事が一つの基準となります。こうする事でどこに何の機能を作ったのかわかりやすくなります。とりあえずノードを作る場所に迷った場合は自分にとってわかりやすい場所にノードを作っていけばオッケーです。
Sphereコンポーネントを右クリック > イベントを追加 > OnComponetBeginOverlapを選択します。
https://scrapbox.io/files/65c895432957cd002411741e.gif
火のダメージを与えるかどうかの判断基準としてBoolean型の変数を用意しておきます。変数を作成して、IsFireDamageEnabledという名前でBoolean型にします。
https://scrapbox.io/files/65c8965be93a0c0023d5e805.jpg
OnComponetBeginOverlapからCastToBP_ThirdPersonCharacterを作成してIsFireDamageEnabledの変数をSetで追加します。Setノードにはチェックを入れます。
https://scrapbox.io/files/65c896ba4fdf8700247cd7ac.jpg
ノード解説
https://scrapbox.io/files/65c896eace35860025b35532.jpg
IsFireDamageEnabled これで他アクタと重なって、そのアクタがBP_ThirdPersonCharacterだった場合にIsFireDamageEnabledをtrueにします。つまり火のコリジョン範囲にプレイヤーが入った瞬間にダメージ判断基準となるBoolean型の変数をtrueにするという処理になっています。
次にSphereコンポーネントを右クリック > イベントを追加 > OnComponentEndOverlapを作成します。
https://scrapbox.io/files/65c8971c2533810023ff6586.gif
OnComponentEndOverlapからは以下の様に作成します。IsFireDamageEnabledにはチェックを入れません。
https://scrapbox.io/files/65c897de450be50024a952d6.jpg
ノード解説
https://scrapbox.io/files/65c898577020f60023286505.jpg
これでプレイヤーが火のコリジョンから出た瞬間にIsFireDamageEnabledはfalseになります。
ではテストするためにOnComponetBeginOverlapとOnComponetEndOverlapノード最後にPrintStringノードを追加しておきます。
https://scrapbox.io/files/65c89892fb609800275649eb.jpg
プレイしてみましょう。火のコリジョン(Sphereコンポーネント)見えないですが、入った瞬間にtrueとテキスト表示されて,出た瞬間にfalseとテキスト表示されるのが確認できます。
https://youtu.be/eiObImXCv9w
😺ではここからはFireDamageOnがtrueになっている間、プレイヤーにダメージを与える処理を書いていきます。
③火のダメージ処理を実装する
ではBP_Fireのイベントグラフにノードを追加していきます。
イベントBeginPlayとSetTimerbyEventノードを作成します。Timeを0.1にして、Loopingにチェックを入れます。
https://scrapbox.io/files/65c8994ca6ecb10025d77f80.jpg
SetTimerbyEventノードとは?
SetTimerbyEventノードはEventピンに接続したカスタムイベントを一定間隔で処理をループさせるノードです。Timeの秒数でループ時間を決めて、Loopingにチェックを入れる事でループさせる事ができます。
Eventピンからドラッグしてカスタムイベントを作成します。名前を「DamegeToPlayer」にします。
https://scrapbox.io/files/65c8998352f28c0024fae9fe.gif
以下のノードを追加します。ApplyDamageノードのBaseDamageには10と入力します。
https://scrapbox.io/files/65c899d4f9aceb00241aa2aa.jpg
ApplyDamageノードとは?
DamageedActorピンに入力されたアクタに対してダメージを与えるノードです。BaseDamageピンにダメージ量を入力します。後に使う「イベントAnyDamage」ノードとセットで使用するノードになります。
全体のノード解説
https://scrapbox.io/files/65c89a1555d3820025c49a17.jpg
①SetTimerbyEventでEventピンに接続されたカスタムイベントをループ処理させます。つまりDamageToPlayerの後続ノードが0.1秒毎に実行されるという事になります。(SetTimerbyEventは一度BeginPlayで実行するだけであとはゲーム中ずっとカスタムイベントを実行させ続けます)
②ブランチでプレイヤーが火のコリジョンに入っている状態か確認して、trueであればApplyDamageノードを起動します。
③ApplyDamageノードはDamagedActorの入力ピンに入力したアクタに対してBaseDamage分ダメージを与えるノードです。
😺つまり火のコリジョンに侵入したらtrueになります。trueの間、プレイヤー側にダメージを伝えるという処理を作った訳になります。
BP_ThirdpersonCharacterを開きます。
https://scrapbox.io/files/65c89c80c8454d00241654da.jpg
変数を作成して名前をPlayerHP,型をFloatにします。
https://scrapbox.io/files/65c89c9bdeb5bd0025383d4e.jpg
コンパイルしてHPを選択した状態でデフォルト値を100にします。
https://scrapbox.io/files/65c89cba3d51b9002435e56b.jpg
まずはこのBp_ThirdPersonCharacterのイベントグラフにイベントAnyDamageノードを作成します。
https://scrapbox.io/files/65c89f886f84a8002475c10a.jpg
イベントAnyDamageノードとは?
先ほどBP_Fire側で作ったApplyDamageノードでこの「イベントAnyDamageノード」を呼んで実行する事ができます。ApplyDamageノードで設定したBaseDamage(ダメージ)がDamageピンから出力されます。つまり入力した10がDamageピンから出力されます。
🐱つまりダメージを指定のアクタに伝えるのがApplyDamageノードで、ダメージを受ける側にイベントAnyDamageノード作ってセットで使用します。なおダメージを与えるという処理は必ずしもこのノードを使わなくても実装する事は可能です。今回は紹介も兼ねて使用していきます。
イベントAnyDamageノードから以下のようにノードを追加します。イベントAnyDamageのDamageピンから「-」と検索して減算(substract)ノードを作成します。PlayerHPからDamageを引いたあとにSetHPでセットします。
https://scrapbox.io/files/65c8a000cb1c1a0024d62162.jpg
ノード解説
PlayerHPからDamage分(つまりApplyDamageで入力した10)を引きます。それをPlayerHPにセットしています。例えばPlayerHPが100なら一回目の処理では100-10=90でPlayerHPに90がセットされます。
プレイしてみて、火のコリジョン範囲内に行くとHPが減っていくのが確認できます。
https://scrapbox.io/files/65c8a08b52f28c0024fb125c.gif
https://scrapbox.io/files/65c8a09ded37f000254cdf57.jpg
これでプレイヤーにダメージを与える火が実装できました。
😺ではここからプレイヤーのHPが0になったら死んだように倒れるモーションを行うという機能を実装していきます。ここから先は少し難しくなるので実装したい方のみどうぞ↓
《実践演習》
ダメージの中止
HPが0以下になったら火のダメージを受けないようにしましょう。
①IsDeathというBoolean型の変数をキャラクターに追加しましょう。
②HPが0以下になったらIsDeathがTureになる処理をプレイヤーに追加しましょう
⓷プレイヤーのIsDeathがFalseであればダメージを継続させる処理をBP_Fireに追加しましょう。
④プレイヤーのHPが0になったら倒れる機能を実装する
BP_ThirdPersonCharacterの追加したノードの最後から作成していきます。
https://scrapbox.io/files/65c8a0dac2271000241411f0.jpg
まずはブランチノードを作成します。「<」と検索してLessThan(以下)ノードを追加します。PlayerHPを上に接続して下は0と入力しておきます。
https://scrapbox.io/files/65c8a0f9549c5e0025dbcd2b.jpg
これでHPが0以下になった時にtrue側の処理が実行されます。
ブランチから以下のノードを作成します。SetSimulatePhyisics(Mesh)を作成します。Simulateにはチェックを入れます。
https://scrapbox.io/files/65c8a12404618a00256c80ef.jpg
SetSimulatePhyisics(Mesh)ノードとは?
SetSimulatePhyisicsはメッシュの物理挙動を有効にするノードです。これを実行するとキャラクターのメッシュに物理シミュレーションが適用されて、キャラクターはそのまま倒れます。
https://scrapbox.io/files/65c8a15604618a00256c81a6.jpg
その後DisableMovement(CharacterMovement)ノードを追加します。
https://scrapbox.io/files/65c8a17be30a0800265409c6.jpg
DisableMovement(CharacterMovement)ノードとは?
DisableMovementはキャラの操作を無効にするノードです。SetSimulatePhyisics(Mesh)ノードでキャラクターが倒れるのですが、倒れた後もキャラクターの操作できてしまうのでこのDisableMovement(CharacterMovement)ノードを使用して操作を無効にします。
物理挙動を有効にした後、つまり死んだ後にはキャラ操作ができないようにします。DisableMovementを作成します。
https://scrapbox.io/files/65c8a1c28744a60029051316.jpg
ノードはこれにて完成です。
これでプレイしてみましょう。プレイヤーが火に触れてHPが0になった時に倒れるはずですが、なぜかキャラは地面をすり抜けてしまっていきます。
https://scrapbox.io/files/65c8a1ec6feeef0026ed1ff6.gif
キャラクターがすり抜ける原因は?詳しく解説
ではここでキャラクターをすり抜ける原因を解説していきます。シンプルに言うとキャラクターのメッシュのコリジョンがすり抜ける設定になっているためです。具体的に解説していきます。
まずBP_ThirdPesonCharacterには実は二つのコリジョンがついています。確認してみましょう。
①まず一個目のコリジョンはBP_ThirdPesonCharacterのコンポーネント「CapsuleCompoent」が該当します。こちらは普段使い用のコリジョンになっています。
https://scrapbox.io/files/65c8a22fed37f000254ce7e8.jpg
②もう一個のコリジョンはこのBP_ThirdPesonCharacterで使用しているメッシュ「SKM_Quinn_Simple」というアセットを開いて表示 > コリジョンを表示させると確認できます↓これはキャラクターのメッシュに正確なコリジョンで特殊な状況の時に使用します。
https://scrapbox.io/files/65c8a272e30a080026540f3c.jpg
③そして今回SetSimulatePhyisics(Mesh)ノードで物理シミュレーションをオンにしたのはメッシュのコンポーネントです。メッシュのコリジョンプリセットを確認してみるとCharacterMeshになっています。
https://scrapbox.io/files/65c8a2a2fb609800275685dc.jpg
④プロジェクト設定を見てみるとCharacterMeshはコリジョンEnabledがQueryOnlyになっています。QueryOnlyというのはコリジョンは有効だが、他アクタに対してすり抜けるオーバーラップの設定になっている事を示します。
https://scrapbox.io/files/65c8a2e7583acf00247eab38.jpg
⑤つまりSetSimulatePhyisics(Mesh)ノードでメッシュのコンポーネントのみ重力がかかるのですが、そのメッシュのコリジョンは他アクタと衝突しないコリジョンプリセットになっています。なのでメッシュだけが落下していってしまう訳です。イメージのgif↓
https://scrapbox.io/files/65c8a312ac76f70025ff8c12.gif
そこでCharacterMeshのコリジョンプリセットを他アクタと衝突する設定にすればメッシュは地面と衝突してすり抜け現象は無くなります。
プロジェクト設定 > エンジン > Collision > Preset > CharacterMesh > コリジョンEnabledをCollisionEnabled(コリジョンを全状況に対して有効)にして承認をクリックします。
https://scrapbox.io/files/65c8a354fb6098002756896e.jpg
プレイしてみましょう!今度はメッシュが地面に衝突するようになっているので、HPが0になったら正しく倒れるモーションが再生されました。
https://youtu.be/54-CBeB_RFE
ダメージを与える火の実装は以上です。
【IsFire側の変更】
https://scrapbox.io/files/65cc44f1494f4b00263e2a95.png
【PlayerCharacter側の変更】
https://scrapbox.io/files/65cc44f49edcce00258007a2.png