テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

物理演算のスリープについて

今回は物理演算のスリープについてです。

Unityでは動作しないオブジェクトはスリープさせ物理演算の処理をスキップする機能があります。これは単純に動いていない物の物理演算を計算するのは無駄だからです。

スリープ状態へは、ある一定の運動量を失った場合に移行します。例えば下のようにオブジェクト落下後一定時間が経過するとスリープします(スリープした場合、黒くなるようにしてみました)


スリープ

スリープを解除(wake up)するには「動いている物・動く物」の接触が必要です。要するにrigidbodyを持つオブジェクトが動作しているオブジェクトに接触する事で解除されます。


接触判定2

逆を言えばスリープ中のオブジェクトにcolliderを接触させてもスリープは解除されません。これはrigidbodyの無いcolliderは静的な物として扱われるため、再計算こそ行われますが接触通知が発生しない為です。単純に考えて、動かない物が動的に接触することは無いという事です。

これが「rigidbodyがどちらかにも無いcolliderは接触判定を出さない」理由です。rigidbodyの無いコライダーは、そもそも動かない想定なので、比較計算が行われないという事です。「接触判定を出すには片方にrigidbodyがあれば良い」がUnityの当たり判定ですが、片方がスリープしていた場合はこのように反応しない場合があるので、動かす物にはrigidbody付けておくと良いです。


接触判定

なおオブジェクトがスリープ時に接触していたコライダーが移動した場合はスリープを解除するといった挙動を持つみたいです。これは、例えば足元に落とし穴が発生したりといった場合に動かすことを想定しているのかもしれません。

ちなみにrigidbody2dの場合は話は違ってきます。どうもUnity2Dの場合はスリープした状態でもオブジェクトが接触(と言うか接近)するとスリープを解除するみたいです。

それと、オブジェクトがめり込んでいる場合はスリープしません。
また余計な負荷が発生するみたいです。
(「めり込む」が物理演算的には超イレギュラーな挙動なので、何か余計な負荷がかかってるのかもしれません。Collision Detectionで挙動予測しておくか、Fixed TimeStepの計算速度を上げてめり込まないようにしましょう)