Unity1Week
先週はunityroomの方でUnity1Weekが開催されていました。
当初は私も微力ながら参加する予定だったのですが、前日からくしゃみが止まらくなる症状が出始め、かつ何故か腰が痛くなるという風邪なのか何なのかよく分からない体調不良に悩まされていた為、断腸の思いで断念させていただきました。
まぁ、unityroomに投稿される作品はUnity1Weekに限らず年々とレベルが高くなっていて、Tweeterなどで上げられている進捗報告の動画を観るたびにビックリしたり落ち込んだりすることも多く、仮に参加出来ていたとしても途中で挫折したかも、、、とか思ったり。参加された皆さん、お疲れ様でした。
時間を制御・・・してるっぽく見せる
さて、以前の記事で一定範囲内にあるオブジェクトに対して、あたかも時間を制御しているかのようにゆっくり動作させる、みたいなことをしたのですが、その時はDoTweenとAnimationのTimescale、Speedを変更する手法で実現していました。
しかし、オブジェクトを動かす手段はDoTweenやAnimation以外でも様々な手法があります。
特に最近では『Human Fall Flat』などが人気になったように物理演算によるオブジェクトの挙動を楽しむゲームも増えてきているので、オブジェクトの位置を直接制御するのではなく、オブジェクトに力を加えることで動かしていく方法も注目されてきています。
Unityで物理演算とえばRigidbody。
なので今回はRigidbodyでも同じようなことができないか探っていきたいと思います。
Rigidbodyを使って動かす
Rigidbodyを使ってオブジェクトを動かす場合はAddForceでオブジェクトに力を加えて動かします。AddForceでは力の大きさと、継続的な力、瞬間的な力、みたいな力の種類を選んで指定します。
今回は下図のようなモデルを用意しました。
赤い弾にAddForceで横方向に瞬間的な力を加えます。
そして横に移動した赤い弾が球体内にいる間だけゆっくりと移動する処理を作ります。
弾が球体内にいるかどうかの判定は前回と同様にTriggerEnterとTriggerExitで判定するのですが、今回の場合はDoTweenの時のように赤い弾だけのTimescaleは変更できません。
また、継続的に力を加えるわけではないのでAddForceのパラメータを変更するわけにもいきません。では、どうするか・・・
赤い弾の速度を直接変更します。
Rigidbodyではオブジェクトのmass(質量)とvelocity(速度)、angularVelocity(回転角速度)を参照&更新できるので、TriggerEnterでvelocity(速度)を遅くして、TriggerExitで元に戻してあげれば良いはずです。なんて単純な手法。
Rigidbody myBody; void Start() { // Rigidbodyの取得 myBody = this.GetComponent<Rigidbody>(); } private void OnTriggerEnter(Collider other) { // 速度を遅くする myBody.velocity *= 0.2f; } private void OnTriggerExit(Collider other) { // 速度を元に戻す myBody.velocity /= 0.2f; }
オブジェクトが回転している場合はangularVelocityに対しても同じような処理を行います。また、OnTriggerExitで速度を元に戻したのに極端に速度が落ちている場合は、OnTriggerEnterでmass(質量)を軽く(=小さく)してOnTriggerExitで元に戻してあげればよい感じなります。
では、実際の動作を見てください
折角だから別の方法も考える
先程は速度を直接変更しましたが、折角Rigidbodyを使っているので別の手法も考えてみました。
次はこんなモデルを使います。
上空にいるウサギはRigidbodyによって自由落下します。
このウサギに対して球体内にいる間だけ逆方向(=上方向)にAddForceで瞬間的な力を繰り返し加えます。要は抵抗を受けてゆっくり落ちるようにします。
Rigidbody myBody; void Start() { // Rigidbodyの取得 myBody = this.GetComponent<Rigidbody>(); } private void OnTriggerStay(Collider other) { // 上方向に力を加える myBody.AddForce(0.7f * Vector3.up, ForceMode.Impulse); }
OnTriggerStayはCollider内にいる間、絶えず呼ばれるのでその中でAddForceを行います。ただ、これだけだと球体から出た時に速度が元に戻らないので、先ほどと同じようにOnTriggerExitでRigidbodyの速度を早くします。
private void OnTriggerExit(Collider other) { myBody.velocity /= 0.15f; }
で、実際の動作はこんな感じになります。
想定通り、落下するウサギにブレーキが掛ったような動作になりました。
これはこれで面白い動きかな、とは思うのですが、速度を直接変更する手法と比べた場合、逆方向の力の大きさとか、速度を戻す係数等はオブジェクトの質量や落下する距離によるので、本当にゲーム内で使う場合は繰り返し実行して調整する必要があります。ちょっと面倒ですね。