【Unity】Rigidbody入門!わかりやすく解説します

昨今のゲームエンジンの進化によって簡単に技術的なハードルがかなり下がり、簡単にリッチな機能のゲームを製作できるようになりました。特に物理エンジンなどは簡単なものであれば、プログラム1行書くことなく実装できるようになりました。
そこで今回のはUnityの物理、衝突判定であるrigid bodyについて解説していきます。

ゲームの物理判定とは?

rigid body は確かに素晴らしいですが、かといって物理処理をすべて自動化されているかというとそうではありません。複数の機能を組み合わせる中で、自分で組まないといけない部分も発生してくるでしょう。なので、rigid bodyに入る前にゲーム空間の物理について簡単に解説します。

アナログとデジタル

物理現象というのは当たり前ですが物体どうしが起こす現象で、我々の現実世界ではさほど珍しくないでしょう。手と手を合わせることも立派な物理現象です。
ただ、ゲームの空間では少し事情がことなります。

ゲームの世界では、実は時間はフィルムのコマのように時間がとびとびなのです。そしてこの1コマのことをフレームといいます。このフレームという単位が非常に重要でゲームの空間では1フレームにつきどのくらいこのオブジェクトが動くという移動量を計算してそれを基にオブジェクトを描画する。この繰り返しでしか動きを表現できないのです。

なので、ゲームの空間だと次のフレームの描画時にオブジェクトと重なっちゃうということがあります。それらを防ぐために、「次のフレームだと当たり判定の領域に入っちゃう、修正しなきゃ」ということで、移動位置を調整してオブジェクトを再描画します。そして、この「修正しなきゃ」という部分にたくさんの複雑な要素(バウンドや摩擦)をいれて、毎フレーム行うことによってまるで現実の物理現象のようにふるまう。これがゲームにおける物理判定の原理なのです。

逆に、一フレームの動く距離を大きくしすぎると、当たり判定のオブジェクトの位置も飛び越えて描画されてしまうので、我々から見るとオブジェクトを貫通してるように見えちゃうこともあります。 ここら辺は解説すると長くなるのですが、その難しいことはUnity君が大体やってくれるので、使い方を見ていきましょう。

Unityの物理判定

さて実際にrigid bodyを使ってみましょう。今回はキューブが自然落下して床に衝突するサンプルを作りたいと思います。今回のものは実はこの程度あればプログラムを書くことなく実装できます。Unityの場合だと当たり判定の属性を持たせて、先ほど言った摩擦やバウンドといったものは物理の属性のパラメータをいじるだけで調節できるのです。少々意味が分かりずらいですが、それは解説しながら説明して行くので作っていきましょう。
先ずは床となるオブジェクトと落下する適当にキューブオブジェクトを作ります。
下の画像から選んで、床はgroundで キューブはcubeとしておきましょう。


ちゃんとオブジェクトが見えるような形でカメラや位置関係を調節。

実はこの時点で既に ground と cubeは当たり判定の属性を持っています。上の画像の右下に部分 colliderというものがありますよね。これが当たり判定の属性(コンポーネント)です。なので作成された時点ですでに当たり判定はもっているのです。
もしない場合は、これから説明する Add Componentから追加してあげてください。

add component

ここからが本番です。
オブジェクトに物理の属性を付与します。といっても先ほどのcollider(当たり判定)のように最初から付与されているわけではないので新たに追加します。下記の画像のようにキューブオブジェクトを選択して Add componentから rigid body を選択しましょう。


これで、物理落下が出来るようになりました。
そのままで、既に重力落下の機能がonになっているのでこれで完成です。
なので上部 ▶のボタンを押して挙動を確認しましょう。

確かに、キューブが床に衝突してとまりましたが、
なんか、違和感がある落ち方ですね。そして何より味気ないです。実際のゲームはこれだと使い物になりません。

physicsMaterial

なので、衝突時の属性も設定してもうちょっと物理エンジンを堪能しましょう。

画像のようにして phisicsMaterial というものを作ります。名前は適当にcubeMaterialとしておきましょう。
これはphysics Material の名前の通り、物理の挙動をもっと詳細に設定するものです。
色々パラメータがありますが、今回はわかりやすくバウンドさせてみましょう。バウンドさせるには、反発係数を設定すればいいので、画像の boundness を設定しましょう。

そしてこれをcubeにセットしましょう。

無事にバウンドしました。これで基本的な動作が理解できたと思うので、次からはプログラムを書いて当たり判定があったときに色々な処理を組み込んでみましょう。

物理判定でオブジェクトを取得する

さてこれで物理属性を付与して実際に動かすことができました。ただこれだけではできることは少ないです。ぶつかったときに相手に特殊な挙動をさせたい。といった場合はプログラムを書く必要があります。ただ、複雑なものを最初から実装しようとすると覚えることがたくさん出てくるので、シンプルに触ったオブジェクトを非表示にしてみましょう。

プログラムを書くために

プログラムを書く前に今回の実装する挙動を整理しましょう。
今回はキューブが床に触れた瞬間に床のオブジェクトを消しちゃう処理です。
これをそれぞれ「タイミング」と「対象」と「対象に対する処理」に分けてみましょう。
なので、「ボールが床と衝突した瞬間」に「床」を「消す」という処理を実行する実装すればいいわけです。これで考え方が明快になったと思うのでこれを基にプログラムを組みましょう。

それぞれの要素はすべてUnityの機能を使っているので、使用するプログラムもUnityのものです。
そしてそのプログラムはどこにあるのかというと
https://docs.unity3d.com/ja/current/ScriptReference/Collider.html
↑です。
上のページのColliderというのは当たり判定です。どこかみたことありませんか。ためしにCube や ground の属性(component)を確認してみましょう。なんたら Colliderという物がありますよね。この中に入っているのです。

前にもいいましたが、これは当たり判定の属性で今から実装するサンプルにはこのCollider が必要になります。なぜなら今からそのCollider の中の機能をプログラムを用いて使用するためです。

それではcubeにプログラムを付与します。Add Componentから適当にCube Scriptと命名してエディターで開きましょう。そして、以下のコードを追加します。

[javascript]
// OnCollisionEnter は触れた瞬間に実行される関数
void OnCollisionEnter(Collision col)
{
// 引数のcolにはぶつかったオブジェクトの当たり判定属性が入る
// SetActiveはゲームオブジェクトの存在を消す
col.gameObject.SetActive(false);
}
[/javascript]

それでは実際に動かしてみましょう。もう一度▶ボタンを押します。

一回バウンドした時点で床が無事に消えてcubeはそのまま落下していきました。
お疲れ様です。

Unity君のお仕事

さて実際にUnity君がなにをやったかをUnityの処理の流れとともに考えてみましょう。
注目すべき点はしつこいですが、Unityはオブジェクトに属性を与えるという点
です。実はUnityの持つコンポーネントは機能を与えると同時にそのオブジェクト本体にアクセスするための入口としても機能するのです。

この事を念頭においてコードを見ていきましょう。

[javascript]
void OnCollisionEnter(Collision col)
[/javascript]

上の部分の col ここに実際に接触した情報が格納されます。そしてその情報はそのオブジェクトのCollider なのです。

しつこいようですが、Colliderはオブジェクトが持つ「属性」なのです。ということは、今持っている「属性」をどのオブジェクトから持ってきたかを完璧に把握しているならそれをとっかかりにそのオブジェクト本体にアクセスできそうではないですか?。

それが次のコードです。

[javascript]
col.gameObject.SetActive(false);
[/javascript]

colの後のgameObjectがオブジェクト本体です。そしてそのオブジェクトを非表示にする機能としてSetActive(false);を使っているのです。

このように、Unityは1 にオブジェクト 2 にコンポーネントです。どのオブジェクトがなんの属性をもっているかという考えそれをどう連携させるかが非常に重要です。

物理判定でのイベント処理

最後にこのイベント処理の種類について詳しくみていきます。先程の例は触った瞬間に発動してていましたが、触っている間、離れた直後とタイミングを色々調節したいことが頻繁にあるでしょう。

https://docs.unity3d.com/ja/current/ScriptReference/Collider.html
上のリンクのメッセージという部分に

当たり判定

OncollisionEnter 触った瞬間
OnCollisionStay 触り続けている状態
OnCollinsionExit 離れた瞬間

先ほどは 「衝突した瞬間」をタイミングとしていたので OnCollisionEnterでしたが、例えば回復するオブジェクトに触れ続けている時間分回復するなどであればOnCollisionStayを離れた瞬間に爆発するとかのギミックを仕込みたい場合はonCollisionExitなど実際に作りたいものの特性を切り替えていきましょう。

また、今回は衝突した場合という物理判定を保持した状態でしたが、Triggerを使えば、そのオブジェクトをすり抜けて且つ触った状態を検知できるようになります。なので、
このエリアにいる間は敵が攻撃してくるようになるものを実装など、衝突だけでなく、挙動を変更させるためのトリガーとしても使用できるようになります。だからこその Triggerなのでしょう。

OnTriggerEnter 触った瞬間
OnTriggerStay 触り続けている状態
OnTriggerExit 離れた瞬間

まとめ

rigid bodyの使い方とそれらの周辺知識と概念を見てきましたがどうでしたでしょうか?
なんども言いますが、ゲームは複数の要素が絡み合ってシステムを構成しているので、今回のようなタイミングを操作する機能や、オブジェクトに属性を付与するrigid bodyなどは工夫やみ合わせ次第で大きな武器になります。自身のゲームを構築して上で色々試してノウハウを貯めていきましょう。