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

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

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

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

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

Q&A

1回答

2748閲覧

RigidBodyのvelocityが反映されない?

sklsobqtnxfklae

総合スコア0

Unity3D

Unity3Dは、ゲームや対話式の3Dアプリケーション、トレーニングシュミレーション、そして医学的・建築学的な技術を可視化する、商業用の開発プラットフォームです。

Unity

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

0グッド

0クリップ

投稿2021/05/08 05:02

物理を持ったオブジェクトを完全停止させる方法は下記のソースで実現が可能と把握しています

rb = GetComponent<RigidBody>();
rb.velocity = Vector3.zero;

であれば

rb.AddForce(transform.foward * 50f,ForceMode.Impulse);
rb.velocity = Vector3.zero; //これが反映されない
rb.AddForce(transform.foward * 1f,ForceMode.Impulse);

このソースで例えると
1行目のrb.AddForce(transform.foward * 50f,ForceMode.Impulse);は無効化され
3行目のrb.AddForce(transform.foward * 1f,ForceMode.Impulse);
のみの弱い力量がオブジェクトに伝わるはずですが
一行目のADDFORCEの勢いも反映した強い力量が伝わるプログラムになってしまいます

なぜ2行目の
rb.velocity = Vector3.zero;
が機能しないのでしょうか?

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

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

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

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

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

ayousanz

2021/05/08 05:17

2行目で速度は一度0になっていると思うのですが,ならないのでしょうか・・?
退会済みユーザー

退会済みユーザー

2021/05/08 14:31

velocityはその時点ではzeroで、 rb.AddForceの結果はUnity内部の物理演算(Internal Physics Update) その時にAddForceに与えられた値の処理が行われvelocityの値は更新されてしまう、という事でしょう。
guest

回答1

0

質量1kg、重力作用なしの球体に下記のようなスクリプトをアタッチし、挙動をちょっと確認してみました。

lang

1using System.Collections; 2using UnityEngine; 3 4[RequireComponent(typeof(Rigidbody))] 5public class AddForceAndVelocityTest : MonoBehaviour 6{ 7 [SerializeField] private Vector3 initialVelocity = Vector3.forward; 8 [SerializeField] private Vector3 impulseA = Vector3.right; 9 [SerializeField] private Vector3 impulseB = Vector3.up; 10 [SerializeField] private bool zeroesVelocity; 11 12 private Vector3 initialPosition; 13 private new Rigidbody rigidbody; 14 private bool triggered; 15 16 private void Start() 17 { 18 this.rigidbody = this.GetComponent<Rigidbody>(); 19 this.rigidbody.velocity = this.initialVelocity; 20 this.initialPosition = this.rigidbody.position; 21 } 22 23 private void Update() 24 { 25 // スペースキーが押されたら、次回のFixedUpdateで実験を行うことにする 26 if (Input.GetKeyDown(KeyCode.Space)) 27 { 28 this.triggered = true; 29 } 30 31 // リターンキーが押されたら初期状態にリセットし、実験をやり直せるようにする 32 if (Input.GetKeyDown(KeyCode.Return)) 33 { 34 Debug.Log("Reset!"); 35 this.rigidbody.position = this.initialPosition; 36 this.rigidbody.velocity = this.initialVelocity; 37 this.rigidbody.rotation = Quaternion.identity; 38 this.rigidbody.angularVelocity = Vector3.zero; 39 } 40 } 41 42 private void FixedUpdate() 43 { 44 if (!this.triggered) 45 { 46 return; 47 } 48 49 this.triggered = false; 50 51 // AddForce実行前の速度を出力してみる 52 Debug.Log($"Frame: {Time.frameCount}"); 53 Debug.Log($"Velocity 0: {this.rigidbody.velocity}"); 54 55 // impulseAを加え、その直後の速度を出力してみる 56 Debug.Log($"Add impulse A: {this.impulseA}"); 57 this.rigidbody.AddForce(this.impulseA, ForceMode.Impulse); 58 Debug.Log($"Velocity 1: {this.rigidbody.velocity}"); 59 60 // velocityをゼロにし、その直後の速度を出力してみる 61 if (this.zeroesVelocity) 62 { 63 this.rigidbody.velocity = Vector3.zero; 64 Debug.Log($"Velocity 1': {this.rigidbody.velocity}"); 65 } 66 67 // impulseBを加え、その直後の速度を出力してみる 68 Debug.Log($"Add impulse B: {this.impulseB}"); 69 this.rigidbody.AddForce(this.impulseB, ForceMode.Impulse); 70 Debug.Log($"Velocity 2: {this.rigidbody.velocity}"); 71 72 this.StartCoroutine(this.PrintVelocityAfterPhysicsUpdate()); 73 } 74 75 private IEnumerator PrintVelocityAfterPhysicsUpdate() 76 { 77 yield return new WaitForFixedUpdate(); 78 79 // 最後に、WaitForFixedUpdateタイミングでもう一度速度を出力してみる 80 Debug.Log($"Frame: {Time.frameCount}"); 81 Debug.Log($"Velocity 3: {this.rigidbody.velocity}"); 82 } 83}

velocityをゼロにしない場合...

図1

  • 最初の速度は(0.0, 0.0, 1.0)
  • 力積(1.0, 0.0, 0.0)を加えても速度は(0.0, 0.0, 1.0)のまま。
  • 力積(0.0, 1.0, 0.0)を加えても速度は(0.0, 0.0, 1.0)のまま。
  • WaitForFixedUpdateまで待つと加えた力積が反映され、速度は(0.0, 0.0, 1.0)から(1.0, 1.0, 1.0)に変わる。

velocityをゼロにする場合...

図2

  • 最初の速度は(0.0, 0.0, 1.0)
  • 力積(1.0, 0.0, 0.0)を加えても速度は(0.0, 0.0, 1.0)のまま。
  • 速度を(0.0, 0.0, 0.0)に書き換えると、直後に速度は(0.0, 0.0, 0.0)に変わる。
  • 力積(0.0, 1.0, 0.0)を加えても速度は(0.0, 0.0, 0.0)のまま。
  • WaitForFixedUpdateまで待つと加えた力積が反映され、速度は(0.0, 0.0, 0.0)から(1.0, 1.0, 0.0)に変わる。

という風に、velocity書き換えは即座に反映されるのに対し、AddForceを行ってもすぐにはvelocityは変化しない様子でした。
物理シミュレーションシステムの裏方ではPhysXが使われていたかと思うのですが、PhysXのドキュメントには...

The forces acting on a body are accumulated before each simulation frame, applied to the simulation, and then reset to zero in preparation for the next frame.

なんて記述がありました。おそらく1570pさんがおっしゃるようにAddForceで加えられた力積は内部的にどんどん積算されていき、シミュレーションを進めるタイミング(「イベント関数の実行順序」の図の中の「Internal physics update」の部分)でその時点のvelocityに反映される仕組みなんじゃないかと思います。

ご質問者さんがおっしゃるような「コード上のある地点までのAddForceを無効化させる」というのは難しいかもしれませんね。
どうやらPhisXにはclearForceなんて機能があるようですが、UnityのRigidbodyにはそれに相当するものはなさそうです。AddForceによって加えられた力積を別途自前で集計しておいて、無効化させたい時にはそれの逆向きの力積を加える...みたいな方法で対処する必要があるんじゃないでしょうか。

投稿2021/05/08 21:42

Bongo

総合スコア10807

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問