夏本番
別に夏の事は嫌いではありませんが、普通に最高気温が体温を超えるのはやめて下さい。
あと『表現の不自由』がそんなに表現したいたら中国に行って習近平の肖像でも燃して下さい。(これも表現の自由です)
壊したい
さて、現在制作中のゲームがシューティングゲームということで、当然のことながら何かしらの物が壊れるとか吹き飛ぶといった破壊表現が必要となってくるわけですが、まぁオーソドックスにパーティクルを表示してオブジェクトを非表示化する、みたいな表現だけではちょっと味気ないので、構造物が壊れて吹き飛ぶような演出も実装してみよう、というのが今回の目的。
こんな感じで壊したい
Unityではそれ(破壊処理)用のアセットもあったりして、Exploderあたりが有名なんでしょうか、メッシュ破壊系のアセットを導入すれば簡単なのですが、それなりにお値段もするし、だいたいドキュメントは英語で読むのが面倒!というわけで自力で何とかしたい。
メッシュ破壊は無理でもオブジェクト本体を飛ばすのはスクリプト何とか出来るので、そちらで実装する方法を考えます。
Rigidbodyを使う
Unityでは物理演算はエンジン側で行ってくれるので、有難くそちらを利用します。
RigidbodyにはAddExplosionForceというメソッドが用意されていて、こちらはその名前の通り、爆発の威力、爆発点、爆発半径を与えると爆発の状態をエミュレートした力をRigidbody加えてくれます。
Rigidbody.AddExplosionForce( float Force, // 爆発の威力 Vector3 Position, // 爆発点 float Radius); // 爆発半径
例えば複数のオブジェクトで構成されている構造体に対して、オブジェクトそれぞれにこのAddExplosionForceを適用してやればまさに爆弾が爆発したような演出が可能になる。。。はず。
ターゲット
今回は以下のような六角形の床と天板、柱が並んでいる簡単な構造体を使ってみました。
当然のことならが全てのオブジェクトにはColliderとRigidbodyが設定されています。
これらにAddExplosionForceで力を加えてやります。ここで第二引数のPositionにはワールド座標を指定することに注意です。ローカル座標ではありません。
また、吹き飛ばしたい全てのオブジェクトのRigidbodyに対してAddExplosionForceを加えることが必要です。
今回のターゲットの場合は全て構造体の子オブジェクトとして定義しているので、Findでオブジェクトを取得し、そのオブジェクに対してGetComponentからRigidbodyを取り出してAddExplosionForceを加えます。
float ExplosionPosition = this.transform.position; foreach (Transform child in ExplosionObjRoot) { child.GetComponent<Rigidbody>() .AddExplosionForce(ExplosionForce, ExplosionPosition, ExplosionRadius); }
で、構造物の中央のワールド座標からAddExplosionForceを加えた結果がこれ
あ、いや、わかるけどさー。もうちょっと、こう・・・
というわけで、爆発点を構造体中央からちょっとだけずらして指定すると
オブジェクトの移動に回転が加わるようになりました。
ただ、これでもちょっと味気ないので、今度は床と天板の中に小さいオブジェクトを仕込んでやり、そちらにもAddExplosionForceを加えるように変更。
ごちゃごちゃしているのが仕込んだオブジェクト
これらに対しても先ほどと同じようにAddExplosionForceを加え、かつ、0.1秒後に床と天板のオブジェクト自体を非表示化する処理を追加します。
これでいいか・・・
で、これを実際のゲームに組み込んでみました。
どうでしょうか?破壊されているように見えますかね?