質問: ### 前提・実現したいこと こちらのサイトを参考に、 Rigidbodyのスリープモードについて検証してみましたが、 書かれている内容と異なる点があったように思えました。 ・質問1 ``` 一見それほど問題はなさそうですが、力を与えられない変更、 例えばそのスリープとなっているオブジェクトの下の床が消えたといった場合に、 オブジェクトは物理演算を行わないのでそのまま宙に浮いたままになったりします。 ``` こちら検証したかったのですが、再現できませんでした。どのようにすれば再現できますか? もしくは仕様が変更されたのでしょうか? ・質問2 質問1が仕様変更したのだとすると、今の所、Rigidbodyがスリープモードになったときに困る不具合として、 「OnCollisionStayが呼ばれなくなる」と、 「Rigidbodyをアタッチしていないオブジェクトが動いて、Rigidbodyに動いているオブジェクトに接触しても、衝突せずにすり抜ける」 ぐらいなのですが、 他に何か思い当たるものがあれば教えていただきたいです。 ・質問3。 トランスフォーム移動でも、スリープを解除するように思えるのですが、 それを証明するようなコードの書き方を教えていただけませんか? ### 試したこと 質問1に関して。 ``` void Update() { Debug.Log(rb.IsSleeping()); } void OnCollisionStay(Collision col){ Debug.Log("stay"); } ``` 重力を効かせたRigidbodyをアタッチしたオブジェクトに、上記スクリプトのログを取りましたが、 スリープがtrueになったとき、OnCollisionEnterが呼ばれなくなるなるのは確認できましたが、 このとき、このスリープしているオブジェクトの下の床オブジェクトを削除したら(シーンビューから選択して削除)、 スリープしているオブジェクトのIsSleepingはfalseになり、スリープが解除され、下に落下しました。 検証方法が間違っている、もしくは、参考サイトの現象の仕様が変更されたのか、教えていただきたいです。 質問2に関して。 下記2点を検証して、そのような挙動になりました。 ・「OnCollisionStayが呼ばれなくなる」 ・「Rigidbodyをアタッチしていないオブジェクトが動いて、Rigidbodyに動いているオブジェクトに接触しても、衝突せずにすり抜ける」 他に考えられる不具合な現象があれば教えていただきたいです。 質問3に関して。 ``` void Update() { if(rb.IsSleeping()){ this.transform.Translate(0.5f, 0, 0); Debug.Log(rb.IsSleeping()); } } ``` これを実行すると、カクカクした動きになる(毎フレームトランスフォーム移動していないような動きになる)のですが、 トランスフォーム移動直後のIsSleepingのログは常にtrueを返します(スリープしたまま)。 何か、トランスフォーム移動でもスリープが解除されていると証明できるコード(できればログで証明できるコード)を 教えていただけませんか? ### 補足情報(FW/ツールのバージョンなど) Unity 2018.3.8f1
回答: Unity 2018.2.3f1ですが確認してきました。 やはり仕様変更入ってるか、私の勘違いだった気がします。 ・質問1 以前こうだったか記憶が無いですが、現行版だと同様の方法で落下しました。 UseGravity・IsKinematic・相手側のRigidbody有無・Staticか否か等も変えてみましたが同様だったので、 現行の仕様は**『「衝突→スリープ→衝突相手が離れる(消える)」の場合はスリープが解除される』**でいいかと思います。 ・質問2 今は特に思い当たらないです。(開発中に何か発見するかもしれませんが) ・質問3 こちらは私の勘違い(または仕様変更が入った)になります。 `transform.Translate`、`transform.position`、`rigidbody.MovePosition`、`rigidbody.position`のいずれもスリープが解除されました。(FixedUpdate内で確認) なお質問文中の質問3のコードでログが常にTrueな理由は、質問への追記・修正依頼に書きましたが 「Debug.Logが呼ばれるのはif文に入っている時のみ=IsSleepingがTrueの時のみ」だからです。 Debug.Logをif文の外に置けば毎フレームの状況が分かります。