見出し画像

Unityで地面が爆発するEffectのつくりかた

こんにちは、こはだです。
普段、音楽イベント向けのVRSNSのワールドを作っていたりします。

ライブパフォーマンスには演出がつきものです。
そして、現実ぽいものを作りたくなることもあるし、現実では不可能なものもやってみたくなります。

今回は、現実ではできない派手な演出として「破壊エフェクト」をやってみることにしました。

破壊エフェクトはなかなかVRSNSで観ることがすくなく、職人さんによって作られているものを見るたびにどうやっているのか興味深々でした。制作者の取材記事を見ると、Houdiniというアプリを使って作っていることが多く、いつかやってみようと思ってもコスト面でも学習面でも敷居が高くて、なかなか手を出せずにいました。

そこで、何かいい方法はないかと日々考えていたところ、Blenderで破壊アニメーションのチュートリアルがあったので、仕組みを学ぶために作ってみることにしました。

Blenderには物理シミュレーションがいろいろあります。

そして、Blenderで作った物理シミュレーションによるアニメーションをベイクして、FBXフォーマットで書き出して、Unityで破片のメッシュとアニメーション両方を取り込もうと思いましたが、破片の一つ一つに複数のアニメーションクリップが生成され、とても扱えるものではない、と思って断念しました。

無限にできるアニメーションクリップ。上のやつだと684MBのファイルになったw

試行錯誤してるうちに、こなごなにしたメッシュをUnityに取り込み、Rigid Bodyコンポーネントを付ければよいのではないかという、あたりまえの結論にたどり着きました。なので、その方向でのワークフローを書いておきます。

大まかな流れ

大まかな手順としては以下の通りになります。

  1. 作ったTerrainのメッシュをFBX形式で書き出す

  2. 上記メッシュをBlenderで読み込み、ポリゴンを粗くする

  3. 破壊アニメーションをさせる部分をポリゴンごとに別オブジェクトにする

  4. 別オブジェクトにしたポリゴンを押し出して立体にする

  5. 押し出して出来た面に別のマテリアルをアサインする

  6. FBXで書き出す

  7. 元の地形と同じ位置に合わせる

  8. 破片オブジェクトにRigidBody、MeshColliderをつける

  9. 衝突物になるオブジェクトを作る

  10. 上記をぶつけるようにアニメーションを組む

  11. 終ったらオブジェクトをDestroyするようにスクリプトをアタッチする

  12. ボタンを押したらオブジェクトが生成されるようにする

1.作ったTerrainのメッシュをFBX形式で書き出す

今回は地面を爆発させるということで、Terrainで作られた地形を加工しないといけません。Unityの公式が、ゲームオブジェクトをFBX形式で書き出すAddOnを提供しており、これを使います。

注:手元のプロジェクトでは、軽量化のために、「Terrain to Mesh」というプラグインを使ってTerrainをさらに分割しています。

ヒエラルキーのオブジェクトを右クリックして「Export To FBX…」です。

2.上記メッシュをBlenderで読み込み、ポリゴンを粗くする

無事、TerrainのメッシュをBlenderにインポートできました。
これを全部使う必要はないので、加工対象を部分的にしたいと思います。位置を決めるために、Unityで上面からのシーンビューのスクリーンショットを撮って、見取り図としてBlenderに読み込みます。

破壊アニメーションを施す範囲に当たりを付けます。
ライブステージ周辺の部分のメッシュ以外を消します。

このメッシュから、破壊させる部分をさらに絞り込みます。ちょうどライブステージの目の前の範囲を選択します。

だいたいこのあたり。Alt+Z で透過にできます。

もとのメッシュがこんなに細かくて、これを扱うとあとで管理が大変なことになりそうなので、粗くします。粗くするために、BlenderのDecimateモディファイアを使いました。

破壊されずに残る場所
破壊させる場所

3.破壊アニメーションをさせる部分をポリゴンごとに別オブジェクトにする

メッシュをこなごなにするには、BlenderのAddOnで「Cell Fructure」というのがあるのですが、あまりいい感じに割れなかったので、今回は力技で別オブジェクトにします。

面選択モードでいっこずつ選択してPキーで別オブジェクト化していく。

3キーを押して面選択モードにして、いっこずつ面を選択してPキーを押して、オブジェクトの分割をちまちまとやっていきます。そんなに細かいポリゴンではないと最初思っていましたが、あとの作業の大変さを予感させてきました。オブジェクトの管理や、ユーザーの表示負荷を考えると、見え方が許す限り、ポリゴン数は極力少ないほうがいいですね。

4.別オブジェクトにしたポリゴンを押し出して立体にする

別オブジェクトにした面をすべて選択して、下方向に押し出します。選択のちTabキーで編集モードにして、Eキーを押したのち、Zキーを2回押して真下に伸びるようにして、ドラッグします。

ところで押し出した直後は、面に妙な陰影が付いていることがあります。そういうときは面が重なっている、面が裏返っている、法線がなにかおかしいのいずれかのケースが考えられます。

この妙な陰影は、Unityに取り込んだときにも変な影になるので、取り除いておきます。編集モードで面選択モードにして、右クリックでコンテキストメニューを出し、Shade Flatで平らにできます。

もこもこしているのを平らになおす。

5.押し出して出来た面に別のマテリアルをアサインする

もともと存在する面はUVがマッピングされていますが、押し出したことによって新たに作られた面には別のマテリアルを貼ります。土っぽいマテリアルを貼ることにしました。

これまた力技ですが、面をぽちぽち選択して、マテリアルをアサインします。別のオブジェクトをまたがって、それぞれの選択された面に一括でマテリアルを貼り付ける操作ができなくて、結構時間がかかりました。

6.FBXで書き出す

Blenderでの作業が終わったので、Unityで取り込むためにFBXを書き出します。

7.元の地形と同じ位置に合わせる

もともと切り出したTerrainの断片と位置を合わせます。Transformからワールド座標をコピーして、インポートしたFBXを同じ階層に入れたうえで、座標をペーストします。

8.破片オブジェクトにRigidBody、MeshColliderをつける

先ほどちまちま別オブジェクトにしてきたものたちに、RigidBodyとMeshColliderのコンポーネントをつけてあげます。前者が重力にのっとった物理的な挙動の付加で、後者は衝突の境界をつくるものです。

9.衝突物になるオブジェクトを作る

爆発したように破片たちを吹っ飛ばすには、同じく衝突の境界をもったオブジェクトでぶつけてあげなくてはいけません。なので、下から押し出すようにキューブを作りました。

Box Colliderが付いています。

10.上記をぶつけるようにアニメーションを組む

衝突が起きて、破片が飛び散って、飛び散った破片が落ち着くまでの流れをアニメーションにします。大まかに以下のように組みました。

  1. 破片たちは下に落ちないように、初期はUse GravityをOFFにする

  2. コライダー付きの四角くて大きいキューブを下から突き上げる

  3. ぶつかる寸前に、破片たちのUse GravityをONにする

  4. ぶつかってしばしのち、破片たちのUse GravityをOFFにする(重力がないので高く飛んでいきます)

  5. さらにしばしのち、破片たちのUse GravityをONにします(下に落ちます)

アニメーションを組みました。オブジェクト数が多いとたいへんですね。。。

11.終ったらオブジェクトをDestroyするようにスクリプトをアタッチする

さて、これであとはこのアニメーションを再生するトリガーをつければ完成!といいたいところですが、一つ厄介な問題があります。
RigidBodyで動いたオブジェクトは、非アクティブにしても場所が戻ることがありません。スクリプトを組んで、最初の場所と回転位置を覚えさせておけばもとにもどすことができるみたいなのですが、スクリプトはつかえません。というのと、Animationの終わり際に初期位置のTransformのパラメータを入れて、場所を戻そうとしましたが、相対座標でしか入れられなくて、しかも値がすべて0が初期位置になっているけど実際はそうじゃなくて、機能しませんでした。(プレイモードにするとPositionに数字は入るのだけど。なぞ)

なので、アニメーションが終ったら、このオブジェクト全体をDestroyして、出現トリガーを引くと都度Createするという方式をとることにしました。

生成物にするので、この一連のオブジェクトをPrefab化して、この中に必要なもの全部が含まれるようにしておきます。出現と同時にアニメーションが再生されればいいので、Animation Controllerも必要なく、Animationクリップのアタッチのみでシンプルな形にしました。そして生成されたことをトリガーにして、おおよそ物理挙動が終わって落ち着く10秒で自動的にDestroyされるようにCCKのスクリプトをアタッチしてます。

12.ボタンを押したらオブジェクトが生成されるようにする

Destroyされるというのは、ヒエラルキーから消えてしまうので、表示させるときは生成する必要があります。生成をさせるトリガーをなにかのボタンに付けておきます。

そして、生成をするためのコンポーネントを何かのオブジェクトに付けます。

この中での大事なのは、Create Item Gimmickの「Spawn Point」で、最初はこの破壊アニメーションのオブジェクトを置いている場所に位置を設定していたのですが、一度Destroyされると、ヒエラルキーの階層外に生成されるので、Spawn位置がだいぶずれてしまいます。なので、位置指定用の空オブジェクトを作って、そこをSpawn Pointに設定するとよいと思います。

Item TemplateはPrefabを指定しておきます。存在と同時に再生されるアニメーションがオブジェクトにくっついているので、置いたままにしておくと入った瞬間いきなり地面が爆発するし、生成させて演出させるため、ヒエラルキーの中にオブジェクトを置く必要はありません。

というわけで出来ましたー!!

以上、駆け足でしたが、地面を破壊するアニメーションのワークフローを書きました。こういう風にオブジェクトをばらばらにするのって、一つ一つのオブジェクトを扱うのと違うむずかしさがあってなかなか大変でした。

BlenderとUnityをはしごしながら思ったのは、けっこう細かい調整をしたくなっても、作業を後戻りしにくかったり、作り直しをするはめになったので、経験を積んで勘をみがくか、ノード式のワークフローみたいなHoudiniなら具合をみながら作り込めそうでいいなーって思いました!

以上です!

もしサポートをいただけましたら、制作活動を行う際のソフトウェア、アセットの購入資金に充てたいと思います!