【UE4】UDamageTypeを使用したダメージエリアの実装


# はじめに

どうも、ろっさむです。



今回はUE4でDamage処理を行う際に使用する `UDamageType`についてまとめたものとなります。



# DamageTypeとは？

UE4内で**ダメージの種類を識別するために使用するクラス**です。ちなみにダメージ源とは無関係です。

例えば炎系の魔法を撃った場合や、ダメージ床を実装する場合に活用ができそうです。DamageTypeにアイコンなどの変数を用意しておいて、ダメージタイプ毎に専用のアイコンを表示すると一気にRPGっぽくなりそうですね。



# 実際にダメージエリアを作成してみる

まずはBPのクラス作成にて `DamageType`を選択します。

![image-20201202002338708.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/930f4445-c253-7e80-5617-ee75dd301298.png)


名前は `Base_DT`としておきましょう。

作成したBPを開いてみると…、何もありません。

![image-20201202002730443.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/02a152ee-ffa5-b48d-ebc2-58336c357896.png)




基本的にはパラメータを弄るのがメインとなります。

![image-20201202002857487.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/d6439a10-fab2-2ccc-415d-007556dbeb1b.png)




| カテゴリ                                              | パラメーター名                   | 概要                                                         |
| ----------------------------------------------------- | -------------------------------- | ------------------------------------------------------------ |
| **Damage Type（基本的にどのダメージタイプにも適用）** | **Caused by World**              | 例えば溶岩や水のようなワールド上のオブジェクトから受けるダメージかどうか（レベルから落ちた場合も含む） |
|                                                       | Scale Momentum by Mass           | 衝突した物体の質量等によって運動量をスケールするかどうか（翻訳怪しい） |
|                                                       | Damage Falloff                   | ダメージの半径に対してダメージ値を減衰させる時の指数の指定。<br />デフォルトが1.0=リニア。2.0=距離の二乗。 |
| Rigid Body                                            | Radial Damage Vel Change         | 放射状の衝撃を適用する場合、衝撃または速度変化として処理するかどうか。 |
|                                                       | Damage Impulse                   | このタイプによってダメージを受けたアクターに適用する衝撃の大きさ。 |
| Destruction                                           | Destructible Impulse             | 破壊可能なメッシュに適用する衝撃の大きさ                     |
|                                                       | Destructible Damage Spread Scale | 破壊可能なメッシュ上でのダメージの広がり                     |



## レベル上にダメージゾーンを用意する

今回は「AdvancedVillagePack」という無料アセット内のあるBP「BP_CampFire」の中央のたき火部分にダメージゾーンを実装します。実際たき火に近付くと熱くて火傷しますし。

![image-20201202012513057.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/ba55d8dc-ed1a-3599-fc47-fb3e701ec14c.png)


ダメージを引き起こす用のボリュームがUE4では用意されているので、そちらも使用しましょう。`Pain Causing Volume`を使用します。

![image-20201202012607235.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/da485734-d179-da82-5421-9cd3d7aa8f86.png)




これらを大きさや位置など大まかに決めて配置してみます。

![image-20201202012650472.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/964a3aa8-10bb-7d20-43b8-bcbe773b3f45.png)




また、それとは別にHP回復用ゾーンも作成してみます。使用するアセットは同じく「AdvancedVillagePack」の「SM_Hay_Small_Var02」です。寝床で回復する感覚だと思っていただければ…。

![image-20201202013138236.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/33ced38a-b6f5-c5b1-a0df-0e54d04a33a3.png)


こちらにも同様に`Pain Causing Volume`を配置します。

![image-20201202013248101.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/5e4a768d-bf0c-f727-75ea-047026897e7e.png)




## 処理の実装



次に今回のダメージエリア用のInterfaceを作成します。名前を `BPI_DamageType`とします。

![image-20201202013923121.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/57bc4e93-a54c-3b17-ff46-513f0f03f464.png)




メソッドは `ProcessDamageValue`という名前で`float`型のダメージ数値を受け取るものを用意しておきましょう。出力時には加工した後のダメージ数値を渡します。

![image-20201202014424481.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/343018bd-c330-35e5-018b-f01cec279a4f.png)


![image-20201202014502051.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/f0ee61f9-18a8-3142-3d8a-8d92665c9800.png)




作成したinterfaceを先ほど作成した `BaseBT`に追加しておきます。

![image-20201202014113795.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/f568ebc0-d9a1-b711-37e8-376323e50315.png)




次に、実際にダメージ数値の加工部分を作成するために、メソッドを`override`して実装しましょう。

![image-20201202014624347.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/77f70cc7-2313-86a6-09dc-6612f0290d9b.png)




ここでダメージ数値に対して掛ける値を用意しておきます。名前を`Multiply`とします。この`Multiply`の値はDamageType毎によって変化させる予定です。デフォルト値は `1`としておきましょう。

![image-20201202014853284.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/b2d87a9d-cade-15f3-56be-af4b1525119f.png)


ダメージ数値をこの値と掛けてから出力するようにします。

![image-20201202014924980.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/c8a59bfc-94e5-3a60-291f-3c9962ce3650.png)




次に `BaseDT`を右クリックして、コンテキストメニューから `CreateChildBlueprintClass`を押下して、子クラスを作成します。

![image-20201202015008308.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/54a60a70-2a89-b785-4dc6-3d91354259e1.png)




今回は火ダメージと回復エリアがあるので、以下の二つの子クラスを作成します。

![image-20201202101246832.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/8ed5f3cd-4b86-f969-e28a-45758d0ce9e3.png)




`FireDT`では `Multiply`の値を`30`とします。

![image-20201202015122808.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/776ee267-3528-e057-5e58-5d2a7d1c331f.png)



`HealDT`では 逆にHPを回復したいので`Multiply`の値を`-15`とします。

![image-20201202015111956.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/033b88d8-50cc-b8d6-afbf-438589198619.png)




次に、先ほどのキャンプファイヤーゾーンに置いた `PainCausingVolume`を選択して、`PainCausingVolume`という項目を確認します。ここの `DamageType`を`FireDT`に設定しましょう。

![image-20201202015210113.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/668ca2f9-2a23-5acb-0ee4-6fc0a998ec1d.png)


こちらの項目の詳細は以下の通りです。

| 項目名         | 概要                                                   |
| -------------- | ------------------------------------------------------ |
| **Pain Causing**   | **このボリュームがダメージを発生させているかどうか**       |
| **Damage Per Sec** | **指定した秒毎にどれくらいのダメージ量を発生させるか**     |
| **DamageType**     | **ダメージの種類の設定**                                  |
| **Pain Interval**        | **ダメージを何秒毎に発生させるかの時間間隔を調整する項目** |
| Entry Pain     | ボリュームに入った瞬間ダメージを発生させるかどうか     |

極端に言ってしまえばこのボリュームだけでもダメージエリアは実装できちゃうんですが、それだと今後同じようなダメージエリアを作った場合にいちいち `Damage Per Sec`を用意したり、ダメージ毎のアクション（例えば溺れたり火傷したり）というのがかなり作りづらくなります。

次に回復ゾーンにおいたボリュームの `PainCausingVolume`を選択して、`PainCausingVolume > DamageType`を`HealDT`に設定しましょう。


![image-20201202102906600.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/d7478fb2-0c2b-8e2c-a955-6896cc12ddc7.png)




最後にプレイヤーキャラクターのBPにて `AnyDamage` から以下のような処理を繋げれば実装完了です。

![image-20201202015653637.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/a61abf3e-0cb1-efb6-3cfb-c872d49a2c89.png)




小さくてちょっと確認しづらいかもしれませんが、HPバーがたき火に入った時に減って、回復ゾーンに入った時に増えているのがわかりますね。

![DamageType.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36899/377e62da-a6b9-55c1-3bb4-b6cde8d6ccc1.gif)




# 参考

- [WTF Is? Class: DamageType in Unreal Engine 4](https://www.youtube.com/watch?v=MLtDgukVG94)
- https://docs.unrealengine.com/en-US/Engine/Actors/Volumes/PainCausingVolumeDetails/index.html
- https://docs.unrealengine.com/en-US/API/Runtime/Engine/GameFramework/UDamageType/index.html