質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

3850閲覧

Rigidbodyのスリープモード

退会済みユーザー

退会済みユーザー

総合スコア0

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2019/04/14 05:59

編集2019/04/14 09:14

前提・実現したいこと

こちらのサイトを参考に、
Rigidbodyのスリープモードについて検証してみましたが、
書かれている内容と異なる点があったように思えました。

・質問1

一見それほど問題はなさそうですが、力を与えられない変更、 例えばそのスリープとなっているオブジェクトの下の床が消えたといった場合に、 オブジェクトは物理演算を行わないのでそのまま宙に浮いたままになったりします。

こちら検証したかったのですが、再現できませんでした。どのようにすれば再現できますか?
もしくは仕様が変更されたのでしょうか?

・質問2
質問1が仕様変更したのだとすると、今の所、Rigidbodyがスリープモードになったときに困る不具合として、
「OnCollisionStayが呼ばれなくなる」と、
「Rigidbodyをアタッチしていないオブジェクトが動いて、Rigidbodyに動いているオブジェクトに接触しても、衝突せずにすり抜ける」
ぐらいなのですが、
他に何か思い当たるものがあれば教えていただきたいです。

・質問3。
トランスフォーム移動でも、スリープを解除するように思えるのですが、
それを証明するようなコードの書き方を教えていただけませんか?

試したこと

質問1に関して。

C#

1 void Update() 2 { 3 Debug.Log(rb.IsSleeping()); 4 } 5 6 void OnCollisionStay(Collision col){ 7 Debug.Log("stay"); 8 }

重力を効かせたRigidbodyをアタッチしたオブジェクトに、上記スクリプトのログを取りましたが、
スリープがtrueになったとき、OnCollisionEnterが呼ばれなくなるなるのは確認できましたが、
このとき、このスリープしているオブジェクトの下の床オブジェクトを削除したら(シーンビューから選択して削除)、
スリープしているオブジェクトのIsSleepingはfalseになり、スリープが解除され、下に落下しました。
検証方法が間違っている、もしくは、参考サイトの現象の仕様が変更されたのか、教えていただきたいです。

質問2に関して。
下記2点を検証して、そのような挙動になりました。
・「OnCollisionStayが呼ばれなくなる」
・「Rigidbodyをアタッチしていないオブジェクトが動いて、Rigidbodyに動いているオブジェクトに接触しても、衝突せずにすり抜ける」
他に考えられる不具合な現象があれば教えていただきたいです。

質問3に関して。

C#

1 void Update() 2 { 3 if(rb.IsSleeping()){ 4 this.transform.Translate(0.5f, 0, 0); 5 Debug.Log(rb.IsSleeping()); 6 } 7 }

これを実行すると、カクカクした動きになる(毎フレームトランスフォーム移動していないような動きになる)のですが、
トランスフォーム移動直後のIsSleepingのログは常にtrueを返します(スリープしたまま)。
何か、トランスフォーム移動でもスリープが解除されていると証明できるコード(できればログで証明できるコード)を
教えていただけませんか?

補足情報(FW/ツールのバージョンなど)

Unity 2018.3.8f1

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sakura_hana

2019/04/16 01:16

物理演算の話なので、Updateでやると実態と齟齬が発生する可能性があります。代わりにFixedUpdateを使って検証してみてください(あんまり変わらないかもですが)。 また、質問3について。Debug.Logが呼ばれるのはif文に入っている時のみ=IsSleepingがTrueの時のみなので、当然ログはTrueだけを返します。Debug.Logをif文の外に置けば毎フレームの状況が分かります。
guest

回答1

0

ベストアンサー

Unity 2018.2.3f1ですが確認してきました。
やはり仕様変更入ってるか、私の勘違いだった気がします。

・質問1
以前こうだったか記憶が無いですが、現行版だと同様の方法で落下しました。
UseGravity・IsKinematic・相手側のRigidbody有無・Staticか否か等も変えてみましたが同様だったので、
現行の仕様は**『「衝突→スリープ→衝突相手が離れる(消える)」の場合はスリープが解除される』**でいいかと思います。

・質問2
今は特に思い当たらないです。(開発中に何か発見するかもしれませんが)

・質問3
こちらは私の勘違い(または仕様変更が入った)になります。
transform.Translatetransform.positionrigidbody.MovePositionrigidbody.positionのいずれもスリープが解除されました。(FixedUpdate内で確認)

なお質問文中の質問3のコードでログが常にTrueな理由は、質問への追記・修正依頼に書きましたが
「Debug.Logが呼ばれるのはif文に入っている時のみ=IsSleepingがTrueの時のみ」だからです。
Debug.Logをif文の外に置けば毎フレームの状況が分かります。

投稿2019/04/16 02:23

編集2019/04/16 02:25
sakura_hana

総合スコア11427

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/04/16 15:40 編集

ご回答ありがとうございます。 なるほど、今の仕様では衝突相手が離れてもスリープが解除されるのですね。 以下、2点質問させていただきたいのですが、 transform系の移動はUpdateで行うものと考えていましたが、 今回は、Rigidbodyのメソッド(IsSleeping)を使っている為に、 FixedUpdateで行ったほうがよいということですか? ご教示いただいて、if文の外でもログを取るようにしました。 void FixedUpdate() { Debug.Log("-start-"); if(rb.IsSleeping()){ this.transform.Translate(0.5f, 0, 0); Debug.Log(rb.IsSleeping()); } Debug.Log(rb.IsSleeping()); Debug.Log("-end-"); } すると、スリープモードに入ってから、それが解除される瞬間の下記のログを見つけました。 -start- False -end- -start- True True -end- -start- False -end- -start- False -end- このログを見て、自分の勘違いに気づけたのですが、 this.transform.Translate(0.5f, 0, 0); Debug.Log(rb.IsSleeping()); とあった場合、Translateした直後には(次の行のログでは)、 スリープが解除される(Falseになる)と思っていたのですが、 そうではなく、 Translateした次のフレーム(つまり、次のFixedUpdateの呼び出し)で、 スリープが解除される(Falseになる)、 という認識で合っていますか?
sakura_hana

2019/04/17 05:44

(私も一度回答した時に誤認してましたが)その通りです。 https://docs.unity3d.com/ja/current/Manual/ExecutionOrder.html こちらにあるように、FixedUpdateの時点ではまだ動作(移動等)を行っていません。 実際に移動等が行われ、スリープ解除されるのはライフサイクル表で言う「Internal physics update」のタイミングです。なのでIsSleepingが変化する(のが取得出来る)のは次のFixedUpdate、ということになります。 FixedUpdateとUpdateのどちらがいいかで言えば、 IsSleepingをシビアに判定したいならFixedUpdate、そうでないならUpdate。 後はrigidbody.MovePositionを使うならFixedUpdate、transform.Translateを使うならFixedUpdateかUpdate(Updateだと副作用があるかもしれないし無いかもしれない)という感じかなと思います。
退会済みユーザー

退会済みユーザー

2019/04/17 14:55

ご回答ありがとうございます。 全て解決しました。 とても勉強になりました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問