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

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

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

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

Q&A

解決済

1回答

5818閲覧

RigidbodyのRelativeメソッドに関して。

退会済みユーザー

退会済みユーザー

総合スコア0

Unity

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

0グッド

0クリップ

投稿2019/01/09 16:06

編集2019/01/09 16:07

前提・実現したいこと

RigidbodyのノーマルメソッドとRelative系のメソッドを使用したときの挙動がわかりません。
ご教示お願い致します。

試したこと

まず、Rigidbody.AddRelativeForceですが、
ローカル座標における力ベクトルを指定するとのことだったので、
this.transform.fowardとかを指定すべきメソッドと解釈しました。

Cubeの回転をあえて、X:0, Y:45, Z:0に設定しておいて、下記コードを実行したら、
図のような想定外の方向に移動してしまいました。
(自分の想定では、CubeのZ軸方向に進む想定でした)。
ちなみにコメントのAddForceだと想定した通りにCubeのZ軸方向に移動します。
(しかし、これも微妙に納得いきません。なぜならば、Rigidbody.AddForceは、
ワールド座標のベクトルを引数に入れるべきメソッドのはずなのに、ローカル座標のベクトル(transform.forward)を入れて、
その方向に動いてしまうので、これが正しい挙動なのか?と思ってしまいます。)

C#

1 void FixedUpdate(){ 2 //rb.AddForce(this.transform.forward * speed * Time.deltaTime); 3 rb.AddRelativeForce(this.transform.forward * speed * Time.deltaTime); 4 }

イメージ説明

Rigidbody.AddRelativeTorqueに関しても同様です。

Cubeの回転をあえて、X:45, Y:0, Z:0に設定しておいて
下記コードを実行したら、よくわからない回転をします。
これも同様にコメントのAddTorqueだと、自身のthis.transform.up、つまりY軸を中心にした回転になりますが、
本当はこの回転こそが、AddRelativeTorqueで実現される回転なのではないかと思っていました。
そして、逆にRigidbody.AddTorqueは、
ワールド座標のベクトルを指定するはずなのに、this.transform.upというローカル座標を指定して、そのローカル軸を中心に回転できてしまう理由もわかりません。

C#

1 void FixedUpdate(){ 2 //rb.AddTorque(this.transform.up * speed * Time.deltaTime); 3 rb.AddRelativeTorque(this.transform.up * speed * Time.deltaTime); 4 }

疑問点をまとめると、以下4点です。

・Rigidbody.AddForceは、本来ワールド座標のベクトルを指定するはずなのに、  ローカル座標のベクトルを指定しても、ローカル座標ベクトルの方向に進む。 ・Rigidbody.AddRelaviteForceに、ローカル座標のベクトルを指定しても、ローカル座標ベクトルの方向に進まず、  よくわからない方向に進む。 ・Rigidbody.AddTorqueは、本来ワールド座標のベクトルを指定するはずなのに、  ローカル座標のベクトルを指定しても、ローカル座標ベクトルを軸にして回転する。 ・Rigidbody.AddRelativeTorqueに、ローカル座標のベクトルを指定しても、  ローカル座標ベクトルを軸にしないで回転する(よくわからない回転をする)。

この4点の疑問に関して、ご教示お願いします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

「ワールド座標のベクトル」、「ローカル座標のベクトル」の認識に関して誤解があるように感じましたが、いざ説明しようと思いますと、うまくお伝えできるかちょっと自信がなくなってしまいました...
いったん分かってしまえば何ということはない理屈かと思います。ご不明点がありましたらコメントいただけますとありがたいです。

シーン上の適当な位置に適当に回したキャラクターを置いたとします。
キャラクターのtransform.forwardを調べるとx、y、zにそれぞれ何かしらの値が入っていますが、それは
ワールド空間の原点(0, 0, 0)から伸びる3つのベクトル(1, 0, 0)、(0, 1, 0)、(0, 0, 1)を基準にした座標値のはずですよね?
つまりtransform.forwardはワールド空間の座標系に基づいたベクトル...「ワールド座標のベクトル」となります。

一方、キャラクターの位置を原点として、そこから伸びる3つのベクトル...transform.rightをXベクトル(1, 0, 0)、transform.upをYベクトル(0, 1, 0)、transform.forwardをZベクトル(0, 0, 1)と見なして、それらを基準にした座標系を考えてもいいはずです。これが「このキャラクターのローカル座標系」となります。

ということは、

C#

1rb.AddForce(transform.forward);

AddRelativeForceに置き換えるには、transform.forwardを「rbのローカル座標系」で表現するとどうなるかを考える必要があります。先ほど申し上げた理屈に基づけば、「ワールド座標のベクトル」であるtransform.forwardと対応する「ローカル座標のベクトル」は(0, 0, 1)...つまりVector3.forwardとなります。
よって、

C#

1rb.AddRelativeForce(Vector3.forward);

としてやると、rbがどちらも同じ動きをするはずです。

投稿2019/01/09 22:18

Bongo

総合スコア10807

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

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

退会済みユーザー

退会済みユーザー

2019/01/10 17:49

ご回答ありがとうございます。 ローカル座標のベクトルを誤解していました。 rb.AddForce(this.transform.forward); rb.AddRelativeForce(Vector3.forward); 上記が同じ処理ということでイメージが掴めました。 ここで、思い付いて試してみたのですが、 下記も同じ処理ということで合っていますか? this.transform.Translate(this.transform.forward * speed * Time.deltaTime, Space.World); this.transform.Translate(Vector3.forward * speed * Time.deltaTime); 同様に、下記も同じ処理ですか? this.transform.Rotate(this.transform.up * speed * Time.deltaTime, Space.World); this.transform.Rotate(Vector3.up * speed * Time.deltaTime); Space.SelfやAddRelativeForceなどのようにローカル座標におけるベクトルを指定するものは、 その引数のベクトルの座標は「そのオブジェクトのローカル座標系」となるということですね? あとは、Space.SelfやAddRelativeForceのローカル座標に Vector3.forwardではなく、this.transform.forwardなどの transform系のベクトルを指定したときに、 よくわかんない動きをすることについてですが、 そもそも「ローカル座標にthis.transform.forwardなどのtransform系のベクトルを 指定すべきではない」と思って、これについては深く考える必要はないですか?
Bongo

2019/01/10 21:59

そうですね。TranslateやRotateの第2引数を切り替えることによって、第1引数をワールド座標系ベクトルと解釈するかローカル座標系ベクトルと解釈するか切り替えることができます。 そして、こちらもおっしゃる通り、TranslateやRotateをSpace.Selfモードで使用したりAddRelativeForceを使って力を加えるときには引数をtransformのright、up、forwardやそれらの組み合わせ...例えばh * transform.right + v * transform.forwardといった形で与えることはまずないでしょう。もちろん分かった上でやっているなら自由に作って構わないと思いますが、うっかり気付かずにやってしまうと意図しない動きに悩むことになりそうです。 以前見かけました別の方のご質問にも「Unity C# 弾の進む方向について質問です。」(https://teratail.com/questions/133315 )や「Unityにてカメラの正面方向を基準にオブジェクトを移動させたい」(https://teratail.com/questions/113541 )といったトラブルがあり、これらもローカル座標系ベクトルが必要な部分に誤ってワールド座標系ベクトルを与えてしまったことによるものだったご様子です。
退会済みユーザー

退会済みユーザー

2019/01/11 14:05

ご回答ありがとうございます。 Space.Selfも今まで正しく解釈できていなかったことがわかりました。 ありがとうございます。 また、ご提示のリンクを拝見し、ローカル座標でthis.transform.forwardを指定したときのよくわかんない動きがわかりました(「45°斜めを向いているオブジェクトが、自身の方向に対してさらに45°斜めに進んだ結果」というご説明で)。 やはり基本的にローカル座標でthis.transform.forward等を使う機会はないということがわかってよかったです。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問