被破壊メッシュ(DestructibleComponent)についてのメモ

# 概要
UnrealEngineでの被破壊メッシュについてのメモです。プラグインの Apex Destruction を使用しています。

[Chaos Destruction](https://docs.unrealengine.com/ja/InteractiveExperiences/Physics/ChaosPhysics/ChaosDestruction/ChaosDestructionOverview/index.html) という新しい破壊システムもあります。(4.26からデフォルトで有効になっているようです)

## 環境
Windows10
Visual Studio 2017
UnrealEngine 4.25


## 参考
[UE4公式：UDestructibleComponent](https://docs.unrealengine.com/en-US/API/Plugins/ApexDestruction/UDestructibleComponent/index.html)
[[UE4] 手軽にオブジェクトを破壊する](https://historia.co.jp/archives/8021/)
[UE4のDestructible Meshを使ってみる](https://pafuhana1213.hatenablog.com/entry/2014/07/12/234658)
[Destructible Troubleshooting Guide](https://michaeljcole.github.io/wiki.unrealengine.com/Destructible_Troubleshooting_Guide/)
[「豚×京都～UE4でなろう破壊神～」（UE4 VFX Art Drive）](https://cgworld.jp/feature/202009-cgw265HSue4pig.html)


# プラグイン
[編集] -> [プラグイン] から [Apex Destruction]を有効にします。

![Plugin.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/33cd18bc-146c-61ab-3f4a-bb3e37b308e7.jpeg)

## 関連ソース
"Engine\Plugins\Runtime\ApexDestruction\Source"


# 被破壊メッシュ

## メッシュ作成
スタティックメッシュを右クリックして`被破壊メッシュを作成`を選択します。

![CreateDestructibleMesh.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/5cd5b716-e79c-70b8-e92f-d8ccde0ecadd.jpeg)

作成したアセットからエディタが開けます。
![Editor.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/91a6d2e4-892d-ce43-cbb4-1c754ecb09dc.jpeg)

`フラクチャメッシュ`ボタンを押下することで被破壊メッシュの作成ができます。
`分解量`のスライダーで破壊状態をプレビューすることができます。

![preview.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/26ca7fd2-7a17-fa99-25d1-3d9348e1bb89.jpeg)

## パラメータについて
ダメージ計算関連のパラメータ以外にも マテリアル設定、LOD設定などもあります。
フラグはよくわからないものが多いです。。

### 被破壊設定 - Damage

| パラメータ名 | 内容 |
|:-----------|:-----|
| Damage Threshold | 破壊するために必要なダメージ量 |
| Damage Spread | ダメージの広がり具合(DamageRadius = Damage*DamageSpread)|
| Enable Impact Damage | 衝突時に破壊可能オブジェクトにダメージを与えるかどうか |
| Impace Damage | 衝突時に適用されるダメージ量の制御値。 (Damage = ImpactDamage * ImpactForce) |
| Damage Cap | ダメージ量の制限値。これは非常に大きなダメージを与えることによって破壊可能なもの全体が粉砕されるのを防ぐのに役立ちます。 |
| Impact Velocity Threshold | ダメージを与えるために必要な速度。剛体が互いに内側にスポーンされると、大きな衝撃力が報告される場合があります。 この場合、2つのオブジェクトの実際の速度は低くなります。 この変数を使用すると、ユーザーは衝突の最小速度しきい値を設定して、衝突力を考慮するためにオブジェクトが最小速度で移動するようにすることができます。 |
| bCustomImpactResistance | オブジェクトの衝突時の跳ね返り量をカスタムするか |
| MaxChunkSpeed | 0より大きい場合、チャンクの速度はこの値を超えることはできません。 この機能を無効にするには、0を使用します（これがデフォルトです）。 |
| Fracture Impulse Scale | 破壊時にチャンクの法線に沿って衝撃力を適用するために使用されるスケール係数。 これは、破片が壊れたときに破片を「押し出す」ために使用されます。 |

### 被破壊設定 - Flag
| パラメータ名 | 内容 |
|:-----------|:-----|
| Accumulate Damage | ダメージ量を記憶するか。設定されていない場合、破壊するには1回のダメージの適用がdamageThresholdを超える必要があります。|
| Asset Defined Support | 設定されている場合、（NxDestructibleChunkDesc :: isSupportChunkを介して）「サポート」チャンクとしてタグ付けされたチャンクは、静的な破壊可能オブジェクトで環境サポートを持ちます。 |
| World Support | 設定されている場合、シーンの静的ジオメトリとオーバーラップするチャンクは、静的な破壊可能オブジェクトで環境をサポートします。 |
| Debris Timeout | 破片の深さ(Debris Depth)以上の塊りがタイムアウトするか。 |
| Debris Max Separation | 破片の深さ以上の塊りが、原点から離れすぎている場合に削除されるかどうか。 |
| Crumble Smallest Chunks | 設定されている場合、最小のチャンクは、流体のクランブル（NxDestructibleActorDescでクランブルパーティクルシステムが指定されている場合）によって、またはクランブルパーティクルシステムが指定されていない場合は単にチャンクを削除することによって、さらに分割できます。 |
| Accurate Raycasts | 設定されている場合、NxDestructibleActor :: rayCast関数は、最も近い可視チャンクヒット内で子チャンクとの衝突を検索します。 |
| Use Valid Bounds | 設定されている場合、NxDestructibleParametersのValidBoundsフィールドが使用されます。 |
| Form Extended Structures | 最初に静的である場合、このフラグが設定されている別の静的破壊可能オブジェクトと接触していると、破壊可能要素は拡張サポート構造の一部になります。 |

### フラクチャ設定 - Voronoi
| パラメータ名 | 内容 |
|:-----------|:-----|
| Cell Site Count | 破壊時の分割数 |


# テスト
## アクター作成
作成した被破壊メッシュを右クリックしてアクターを作成します。
![createactor.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/e4e53203-672e-252b-bcbb-d5cd12b08c00.jpeg)

この方法で作成したアクタークラスは親クラスが `Actor`クラスのようです。（`Destrictible Actor`クラスではない）


## イベント実装
物理エンジンまかせにもできますが、ここでは直接ダメージを送って破壊してみます。
関連ソースとメソッドは以下になります。

```cpp:DestructibleComponent.h

// ダメージ受け取り
UFUNCTION(BlueprintCallable, Category="Components|Destructible")
virtual void ApplyDamage(float DamageAmount, const FVector& HitLocation, const FVector& ImpulseDir, float ImpulseStrength) override;

// 範囲ダメージ受け取り
UFUNCTION(BlueprintCallable, Category="Components|Destructible")
virtual void ApplyRadiusDamage(float BaseDamage, const FVector& HurtOrigin, float DamageRadius, float ImpulseStrength, bool bFullDamage) override;

```

## ダメージイベント
`ApplyDamage`を使ったBP例です。
![ApplyDamage2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/834836d0-48fb-7ccd-4224-bbea7dd0123b.jpeg)

`ApplyRadiusDamage`を使ったBP例です。ダメージ範囲の中心位置がメッシュ位置なのでダメージの減衰は起こりません。
![ApplyDamage1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/f3efde99-2ce1-3719-00b5-c496971a8cc0.jpeg)

物理エンジンに関係なく、直接ダメージを与えることができます。


## 破壊イベント受け取り
破壊のイベント受け取りはコンポーネントにイベントをバインドすることで受け取り可能です、以下コード例。

![OnEvent.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/77a20111-2381-8874-2c97-86554d1082f0.jpeg)

## コリジョン設定
DestructibleComponent のコリジョン設定を変更することで破片がポーンにぶつからないようにもできます。用途によっては設定を書き換える必要があります。

![CollisionSetting.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/f9d699a9-7db7-c867-f9b7-3a10bc350930.jpeg)


## メッシュリセット
破壊されたメッシュを戻すには、アクターをリスポーンするか、被破壊メッシュを再セットすることで可能の様です。

![Reset.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/66d2c555-2b6e-ec7a-f8f0-4fd11afa4dd9.jpeg)


# 結果
分割して吹っ飛びます。
パーティクルなどを設定するとよりそれっぽくなると思います。
![result01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/fd2e5983-edcc-c14b-1091-49817147be38.jpeg)

![result02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/3c84f4a9-ca57-0f38-1a1f-20844ece1ef0.jpeg)



# まとめ
単純に物理任せで使用してもそれっぽくなり、見た目が楽しいです。
が、処理負荷は重くなるため多用するなら注意が必要です。