8/8は発破の日!Fracturing & Destructionでオブジェクトを発破する

この記事は「Unity アセット真夏のアドベントカレンダー 2020 Summer!」の8日目の記事となります。

昨日のアドベントカレンダー記事は潮留 様の「Arbor3をおすすめしたい3つの理由
明日のアドベントカレンダー記事はホロウさま 様の「Anyportraitでゲームに用いた実装
になります。

この記事で紹介するアセット

今回の記事では「Advanced Tools Mega Pack」に含まれている「Fracturing & Destruction」について紹介いたします。

以前は単体でも販売されていたはずですが、バージョンアップを機に単体販売は終了してしまったようです。残念!

動作確認環境

この記事は以下の環境で動作確認、検証を行いました。
・Windows 10
・Unity 2019.2.21 – 2019.4.3.f1

まずはお知らせ

こちらの記事を書くためにいろいろ検証した結果、今回紹介するFracturing & Destructionのアセットは最新のUnityに対応していないことがわかりました。
Unity 2019.3以降のバージョンを利用すると、「Enable Prefab Usage」のオプションが正常に機能せず、プレハブ化の機能が利用できませんでした。
Unity 2019.2以下のバージョンであれば正しく動作しました。
アセットのバージョンアップが行われることを期待しましょう!

まずは破壊してみよう!

アセットの導入から破壊可能なオブジェクトを作成するまでStep By Stepで紹介いたします。

プロジェクトを新規作成します。

プロジェクトが作成され、Unityエディタが起動します。

アセットストアより「Advanced Tools Mega Pack」をインポートします。

多数のパッケージが表示されますが、今回は破壊系のパッケージに絞ってインポートを行います。

パッケージがインポートされました。
次に床を作成します。ヒエラルキービューで右クリックし、3D Objects > Plane を選択します。

破壊可能オブジェクトとして、球を作成します。
ヒエラルキービューで右クリックし、3D Objects > Sphere で作成できます。
Transform > Position > Y の値を7.5に設定します。
(このオブジェクトが破壊可能なオブジェクトの「元」として使用されます。)

いよいよ破壊可能なオブジェクトを追加します。
ヒエラルキービューで右クリックし、Create Other > Ultimate Game Tools > Fractured Object を選択します。

作成したFractured Object を選択し、インスペクターの「Source Object」に先ほど作成したSphereオブジェクトを設定します。

Fractured Object を選択し、インスペクターの下部にある「Compute Chunks」をクリックします。
(オブジェクトが粉砕された時の形状が計算されます。)

Compute Chunksボタンをクリックすると、以下のダイアログが表示されるので、Yes を選択します。
(元なったオブジェクトを非表示にしますか? の選択となります。)

計算が終わると、Fractured Object配下に多数のオブジェクトが生成されます。

最後に、Unityエディタの再生ボタンを押せば、砕け散るオブジェクトを眺めることができます。
お疲れさまでした!

各種パラメータ紹介

Fracture Objectには多数のパラメータが準備されており、これらを各種調整することで多彩な破壊表現を行うことができます。各パラメータについて、ざっと紹介していきます。
基本的に公式ドキュメント「Fracturing & Destruction Help」のDeepL翻訳 + 意訳になります。

Mainセクション

Source Object
フラクチャーオブジェクト(破壊可能オブジェクト)の元になるGameObjectを指定します。元となるオブジェクトは削除されません。

Island Generation
メッシュ分割時に孤立したメッシュを検出し、分離されたチャンクにします(例:U字型を水平にスプティングした場合、2つのオブジェクト(片方の手には底辺、もう片方の手には2つの先端が同じオブジェクト)ではなく、3つの島生成オブジェクト(底辺と2つの先端が分離したもの)が得られます)

Chunk Interconnection
チャンク間の内部接続グラフを生成し、構造的な挙動を持つようにします。これは、チャンクがどのように相互接続されているかによって崩壊したり、ワールドに接続されていたりするようなインテリジェントな破壊を可能にします。具体的な例としては、円弧と円柱のサンプルシーンがあり、円柱を破壊すると、上にあるチャンクも同様に崩壊します。チャンクをワールドに接続する方法については、Support Planesを参照してください。
(Support Planesについては別途補足します)

Start Static
Chunk Interconnection がチェックされていて、サポートプレーンやサポートチャンクが定義されていない場合、オブジェクトは開始時に崩れてしまいます。最初の接触までオブジェクトを静止させたい場合にチェックを入れてください。

Interconnection Min Area
接続された2つのチャンクが接続されているとみなすための最小面積。この値をゼロに設定すると、すべてのチャンクが接続されているとはみなされず、どんなに小さくても少なくとも共通の面の面積を共有しているチャンクのみが接続されているとみなされます。チャンクを再計算しなくても、この値を変更することができます。

Interconnection Strength
オブジェクトに接続されているチャンクがヒットして取り外された場合、接続されているチャンクが何個取り外されるかを制御します。0.0であればオブジェクト全体が崩れ、1.0であれば接続されたチャンクは切り離されません。チャンクを再計算しなくても、この値を変更することができます。

Support Hor. Strength
チャンクがオブジェクトに固定されたままでいるために、サポートチャンクからの水平方向の最大距離を制御します。その距離がこの値より大きい場合、それは落下します。例えば、円弧と円柱のサンプルシーンで、隣り合っている円柱を破壊すると、サポートチャンクを含む最も近い円柱まで水平方向に距離がありすぎると、上部も同様に崩壊します。

Support Is Indestructible
これを有効にすると、サポートチャンクはオブジェクトから破壊/削除することができません。

Island Max Connect Dist.
ソースオブジェクトが存在し、アイランド生成がアクティブな場合、内部の複数の閉じたメッシュを検出することがあり、そのうちのいくつかは他のメッシュに接続されている可能性があります。これは、2つの島が接続されているとみなすために、1つの島からの面が別の島からどのくらい離れているかを制御します。

Total Mass
オブジェクトの総質量。各チャンクの質量は、そのサイズとこの値に応じて計算されます。チャンクを再計算しなくても、この値を変更することができます。

Chunk Physic Material
各チャンクに割り当てられる物理マテリアル。

Min Colder Volume
この値以下のボリュームを持つチャンクは、コリジョンを高速化するためにメッシュコライダーの代わりにボックスコライダーを持つようになります。

Cap Precision Fix (Adv.)
メッシュに奇妙な三角形が追加されたり、予期せぬクラッシュが発生した場合にのみ、この値を0から変更してください。これは通常、浮動小数点エラーにより非常に薄い面を持つメッシュで発生します。通常は0.001から0.02の範囲が良いでしょう。値を大きくすると、いくつかのSPT(?)で目に見える小さな変化が発生します。問題のある面が2つか3つしかない場合は、別のランダムシードを使用するのも一つの方法です。

Reverse Cap Normals
何らかの理由で内部の面が逆になっている場合は、チェックをONにしてください。

Chunk Collider Type
通常の動作をしたい場合は、コライダーを使用してください。壊れやすいオブジェクトに衝突したときに、高速で動いているオブジェクトが運動量を失うのを防ぎたい場合にのみ トリガーを使用してください。
例えば、高速で発射された弾がガラスに当たった場合、コライダーを利用すると弾のスピードが大幅に落ちてしまいます。(ガラスに弾が当たった場合、現実では弾のスピードはほとんど落ちませんよね?)
その一方で、オブジェクトが破壊対象のオブジェクトに対して十分な質量/速度を持っていない場合、トリガーを使用すると、単純に通過するようになります。(非現実的な結果になります)

Fracture & Interior Materialセクション

これらのパラメータは、スライスの実行方法と内部材料を制御します。

Fracture Method
BSP、Voronoiの2種類のアルゴリズムが選択できます。

BSP選択時のパラメータ

Number Of Chunks
メッシュを分割するチャンクの数。

Slice In World Space
スライスをローカルオブジェクト空間で行うか、ワールド空間で行うかを制御します。フラクチャリングされたオブジェクトではなく、元のオブジェクトの向きが考慮されることに注意してください。

Slice Regularly
セットされている場合、スライスは常に全軸でチャンクサイズを最小化するように実行され、そうでない場合は与えられた確率でランダムに実行されます。

Slice X Probability
Xでスライスが実行される確率(0-1)

Slice Y Probability
Yでスライスが実行される確率(0-1)

Slice Z Probability
Zでスライスが実行される確率(0-1)

Slice Size Variation
0.0では、チャンクの大きさがより均等になります。値を大きくすると、チャンクの大きさにばらつきが出てきます。

Slice X Variation
X平面内のスライスの角度変化。

Slice Y Variation
Y平面内のスライスの角度変化。

Slice Z Variation
Z平面内のスライスの角度変化。

Voronoi選択時のパラメータ

Use Volume Optimization
大きなメッシュを使用する場合や、巨大な空の体積を使用する場合に、フラクチャリングの計算を高速化します。

Use Proximity Optimization
Voronoi計算を高速化するために使用します。いくつかのケースでは、交差するチャンクを導入することができます。

Use Multithreading
いくつかのVoronoi計算ステップにマルチスレッドを使用します。完全にテスト/最適化されていませんが、動作するはずです。何か問題が発生した場合のみ無効にしてください。

Cells In Local X
VoronoiはX * Y * Zのセルを生成します。これはX次元で生成するセルの数です。

Cells In Local Y
VoronoiはX * Y * Zのセルを生成します。これはY次元で生成するセルの数です。

Cells In Local Z
VoronoiはX * Y * Zのセルを生成します。これはZ次元で生成するセルの数です。

X Cells Variation
値が大きくなると、X次元のセルの大きさや位置の違いが大きくなります。

Y Cells Variation
値が大きくなると、Y次元のセルの大きさや位置の違いが大きくなります。

Z Cells Variation
値が大きくなると、Z次元のセルの大きさや位置の違いが大きくなります。

Interior Material
チャンクの内側のマテリアルを指定します。

Interior Mapping U Tile
U 内側の面のマッピングのタイリング。

Interior Mapping V Tile
V 内側の面のマッピングのタイル化。

Eventセクション

Chunk Detach From Object Due To Physics Collision

Min Impact Mass
衝突時にこの物体からチャンクを切り離すために必要な最小質量。

Min Impact Velocity
このオブジェクトからチャンクを切り離すために、オブジェクトが衝突しなければならない最小速度。

Exit Force
衝撃によりチャンクが切り離された場合は、この値が適用されます。

Upwards Modifier
Exit Forceが設定されているチャンクに上向きの爆発効果を追加します。(値が0.0の場合は何の効果も追加されず、2.0の場合はチャンクの下2の距離から力を加えることを意味します。)

Detach Sound
衝撃でチャンクが外れたときに、衝突地点でこの音を再生します。

Instance Prefab List (1 Randomly Spawned On Detach)
プレハブのリストです。衝突によってチャンクが切り離された場合、このリストからランダムなプレハブが選ばれ、衝突地点でインスタンス化されます。パーティクルや爆発に使用します。

Call Method Name
インパクトがトリガーされたデタッチチャンクイベントで呼び出されるメソッド名 (Call GameObjectのパラメータとスクリプト参照)。

Call GameObject
メソッドが呼び出される GameObject。スクリプトのリファレンスを参照してください。

Free (Detached) Chunks

Min Chunk LifeTime
フリーチャンクの最小寿命。チャンクの有効期限が切れると削除されます。

Max Chunk LifeTime
フリーチャンクの最大寿命。チャンクの有効期限が切れると削除されます。

Offscreen LifeTime
フリーチャンクがこの秒以上、可視画面の外にある場合は削除されます。

Min Impact Mass
フリーチャンクが衝突イベントを発生させるために必要な最小質量。

Min Impact Velocity
フリーチャンクが衝突イベントを発生させるために必要な最小速度。

Max Simult. Sounds
同時に再生される衝突音の最大値です。

Collision Sound List (1 Randomly Played On Collision)
サウンドのリストです。フリーチャンクの衝突では、このリストからランダムな音が選ばれ、衝突地点で再生されます。

Max Simult. Prefabs
同時に存在する衝突プリファブの最大数。

Collision Prefab List (1 Randomly Spawned On Collision)
プレハブのリスト。フリーチャンクの衝突時には、このリストからランダムなプレハブが選ばれ、衝突地点でインスタンス化されます。これはパーティクルや爆発に使います。

Call Method Name
フリーチャンク衝突時に呼び出されるメソッド名(Call GameObjectのパラメータとスクリプトリファレンスを参照)。

Call GameObject
メソッドが呼び出される GameObject。スクリプトの参照を参照してください。

When Explode() Is Called Through Scripting (Explosions)

Explosion Sound
このオブジェクトで Explode() が呼び出されたときに再生されるサウンド。

Random Prefabs
オブジェクトのランダムな位置にインスタンス化するプレハブの数。

Instance Prefab List (Spawned Randomly Around)
プリファブのリストです。Explode() が呼び出されると、オブジェクトのランダムな位置にランダムな数のプレハブがインスタンス化されます。パーティクル/爆発に使用します。

When Impact() Is Called Through Scripting (f.e. Missiles)

Impact Sound
このオブジェクトで Impact() が呼び出されたときに再生されるサウンド。

Impact Prefab List (1 Randomly Spawned On Impact)
プレハブのリスト。Impact() が呼ばれると、ランダムなプレハブがインパクトポイントにインスタンス化されます。これはパーティクルや爆発に使用します。

On Every Chunk Detach Event (Collision, Impact, Explosion, User scripted detach…):

Call Method Name
チャンクが理由に関係なく切り離されたときに呼び出されるメソッド名(Call GameObjectのパラメータとスクリプトリファレンスを参照)。

Call GameObject
メソッドが呼び出される GameObject。スクリプトの参照を参照してください。

Support Planes

サポートプレーンは、どのチャンクがサポートとしてタグ付けされるかを制御します。負の面(面-Yで示された面)にあり、その限界内にあるすべてのチャンクはサポートとしてマークされます。

サポートとして機能するチャンクは破壊することができず、オブジェクトを一緒に保持します。チャンクはサポートチャンクに(直接または他のチャンクを介して)接続されている必要があります。これにより、チャンクが空中で静止したままになるのを防ぎ、リアルな崩壊動作が可能になります。

Support Planesのパラメータ

Plane Name
シーンビューに表示される名前です。

Local Position
破断した物体を基準とした平面位置。

Local Rotation
破断した対象物を基準とした平面回転。これを使用して、例えば天井などへのアタッチメントを変更します。

Local Scale
サポートプレーンのスケール

Delete
サポートプレーンを削除する

その他のパラメータ

Random Seed
それぞれのシードは、異なるフラクテッドオブジェクトを作成します。結果に満足できない場合は、シードを変更してください。

Preview Chunks
生成されたチャンクをプレビューするには、このスライダーを使用します。

Always Gen. Colliders
チャンクが計算されるたびにコライダーを生成します。

Show Chunk Connections
チャンクがどのように相互に接続されているかを示します。

Color Chunk State
シーンビューのチャンクに色をつけて、どのチャンクがサポートチャンクで、どのチャンクが直接または間接的にサポートチャンクに接続されていないかを表示し、構造の完全性をチェックするときに落ちるようにします。

Color Chunks
エディターウィンドウまたはゲームウィンドウ(ゲームウィンドウ内での着色はプレイモード中のみ)でランダムにチャンクを着色します。

Enable Prefab Usage
チャンクとコライダーのメッシュが計算されたときに、ディスク上のアセットファイルに保存されます。このオブジェクトをプレハブに追加したい場合に使用します。そうしないと、メッシュとコリダが正しくインスタンス化されません。

Output Console Info
コンソールウィンドウにメッセージや警告を出力します。

Compute Chunks
チャンクを計算し、粉砕されたオブジェクトを生成します。

Delete Chunks
チャンクを削除します。

Use Concave Collider
外部の 「Concave Collider」 ユーティリティを使用して、メッシュ コライダーの生成方法をより詳細に制御できます。(Advanced Tools Mega Pack内に同梱されています)

Algorithm
凸分解アルゴリズム。通常はFASTを選択しておけば問題ありませんが、適切に動作しない場合は他のものを使用してください。

Max Collider Vertices
コライダーが持つことができる最大の頂点を制限します。

Compute Colliders
チャンクコライダーを計算します。

Delete Colliders
チャンクコライダーを削除します。

イベントについて

イベントを利用すると、オブジェクトが破壊されたタイミングで任意のスクリプトを実行できます。
使用方法は、実行したいスクリプトをGameObjectアタッチし、呼び出すメソッドをFracture Objectのイベント欄に設定するだけです。
実際に簡単なイベント処理を設定してみたいと思います。

スクリプトの作成
以下のようなスクリプトを作成しました。
オブジェクトが破損したときに、破片の数をカウントするためのスクリプトとなります。

using UnityEngine;
using UnityEngine.UI;

public class DetachCount : MonoBehaviour
{
    public Text text;
    private int detachCount = 0;

    public void incrementDetachCount()
    {
        detachCount++;
        text.text = "Detach Count:" + detachCount;
    }
}

スクリプトのアタッチ
空のオブジェクトを作成し、上記のスクリプトをアタッチします。

カウント表示用のUIテキスト作成
カウント表示用のUI Textを作成します。
作成したTextは、先ほど作成したスクリプトのtextプロパティに設定します。

Fracture Objectのイベントを設定
Fracture Objectのイベント設定欄に、先ほど作成したゲームオブジェクトを設定し、呼び出すメソッドに「incrementDetachCount」を設定します。

動作確認
これで、オブジェクト破壊時にイベントが実行され、破片がカウントされるようになります。
早速実行してみましょう。

イベント設定の概要は以上です。

プレハブについて

生成したFracture Objectをプレハブとして使用する場合、「Enable Prefab Usage」にチェックを入れる必要があります。

検証したところ、こちらの機能はUnity 2019.03以降のバージョンでは正しく機能しませんでした

サポートプレーンについて

サポートプレーンを利用すると、よりリアルな破壊表現が行えます。
柱などのオブジェクトの場合、サポートプレーンを使って固定されている場所を指定することで、より現実に即した破壊表現が行えるようになります。

以下のシーンは、全く同じパラメータで作成した破壊可能な柱に対して、ボールを衝突させたときの動作画面になります。サポートプレーンの有り/無しで壊れ方に大幅な違いが出るのが確認できるかと思います。
画面上部がサポートプレーンあり、画面下部がサポートプレーン無しとなります。

実際に使用した際の注意事項

チャンク計算時にUnityを巻き込んで落ちる時がある

複雑な形状を利用したり、極端に細分化したチャンクを生成しようとした場合にUnityを巻き込んでプログラムが落ちることがあるため、「Compute Chunks」ボタンを押す前にプロジェクトを保存しておいたほうが安全です!

公式のヘルプでは「Random Seedを変更する」「Cap Precision Fix (Adv.)」を増やしてみる。というアドバイスが記述されていました。

Skinned Meshは利用できない

残念ながらスキンメッシュオブジェクトには利用できません。
以下の動画は「Robot Kyle」に含まれている「Robot2」メッシュをSource Objectに設定した際の動画です。
エラーとなり、チャンクの計算が行えませんでした。

おまけ:発破しよう!

最後に、Fracturing&Destractionに付属している「Explosion Source」とAsset Storeで配布されているフリーの爆発エフェクトを利用して、オブジェクトを発破しましょう!

使用したフリーのエフェクトアセットは以下になります。
Procedural fire

破壊可能オブジェクトの準備
シーンにCubeを追加し、PositionはY = 10に設定、ScaleはX,Y,Zすべてを20に設定しました。
ついてにブルーのマテリアルを作成し、割り当てています。

床の追加
床となるPlaneを追加し、大きさはX,Z = 100で作成します。

Fracture Object作成
実際に破壊対象となるオブジェクトを作成します。
Fractured Objectを追加し、以下のパラメータで生成しました。赤枠内は変更箇所で、画像には写っていないのですが、「Interior Material」を設定しておけば、オブジェクト破壊時に断面がピンク色(マテリアル未指定)になってしまう状態を防げます。
設定が終わったら「Compute Chunk」ボタンを押して計算を開始しましょう。

上記のパラメータで計算を行うと、破片が1000個(!)に分割されるため、計算が終わるまで少々時間がかかるかもしれません。
計算が終わると、以下のようにオブジェクトが細分化されたことがわかります。

サポートプレーンの追加
よりリアルな破壊表現とするため、サポートプレーンを追加します。
一番下部に存在する破片のみ、サポートプレーンの範囲となるように調整を行いました。
(サポートプレーンの対象になっている場合、破片オブジェクトの色が変わります)

Explosion Sourceの追加
ヒエラルキービューで右クリック > Create Other > Ultimate Game Tools > Explosion Source を選択すると
Explosion Sourceオブジェクトが作成できます。

Explosion Sourceのパラメータ設定
Explosion Sourceのパラメータを以下のように設定しました。
Pos Start, Pos End, Move Duration を指定することで、Pos StartからPos EndにMove Durationの時間を掛けて移動するという動作が作成できます。
Influence RadiusとForceはそれぞれ力の発生範囲と強さになり、大きくすればするほど破片も派手に飛び散るようになります。

エフェクトの追加
Explosion Sourceオブジェクトは実際のゲーム画面には描画されないため、見た目を派手にするためにエフェクトを追加します。
冒頭で紹介した「Procedural fire」に含まれている「Magic fire pro red」をExplosion Sourceの子オブジェクトとして追加します。
Magic fire pro redのスケールはお好みで調整してみてください。

以上ですっ!
以上でシーンの設定は完了です。シーンを再生してみて、オブジェクトがどのように破壊されるか観察してみましょう!

最後に

いかがでしたでしょうか?「Fracturing & Destraction」アセットを利用すれば、簡単に破壊可能なオブジェクトを生成することが可能です。こちらの記事で紹介できた機能はアセットの一部の機能のみになりますので、より深く知りたい方は公式ページYoutube動画を参照していただけると幸いです。

残念ながら最新版のUnityでは一部機能が正しく動かないため、まずはアセットのバージョンアップが行われることを期待しましょう!

Enjoy Destruction!