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

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

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

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

Q&A

解決済

1回答

6413閲覧

rotationとeulerAnglesに関して。

退会済みユーザー

退会済みユーザー

総合スコア0

Unity

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

1グッド

2クリップ

投稿2019/01/29 15:34

前提・実現したいこと

rotationとeulerAnglesの関係に関してご教示お願いします。

該当のソースコード

下記2つのコードは同じ処理という認識で合っていますか?

C#

1transform.rotation = Quaternion.Euler (0, 10, 0); 2transform.eulerAngles = new Vector3 (0, 10, 0);

同様に下記2つのコードは同じ処理という認識で合っていますか?

C#

1transform.localRotation = Quaternion.Euler (0, 30, 0); 2transform.localEulerAngles = new Vector3 (0, 30, 0);

試したこと

実際に上記のそれぞれのコードを実行して、ゲームオブジェクトのインスペクタの回転角を確認しました。
上記2つとも、それぞれのコードで同じ角度を示すことを確認しました。
結果から考えれば同じ処理と判断してよさそうな気もしますが、
今まで回転角の質問をして、実は認識が違っていたということが多々あった為、念の為、質問させていただきました。
上記がそれぞれ同じというのは、自分のメモに書いてあったのですが、この同じとする根拠は何だろうと、ふと思い、
過去の質問を見返したり、検索したりして調べてみたのですが、
上記のrotationとeulerAnglesの設定処理が同じと明言されている記事等が見つからなかった為、質問させていただきました。

退会済みユーザー👍を押しています

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

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

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

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

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

guest

回答1

0

ベストアンサー

それぞれ、UnityCsReference/Transform.bindings.cs at master · Unity-Technologies/UnityCsReference · GitHubによると...

C#

1 // The rotation as Euler angles in degrees. 2 public Vector3 eulerAngles { get { return rotation.eulerAngles; } set { rotation = Quaternion.Euler(value); } } 3 4 // The rotation as Euler angles in degrees relative to the parent transform's rotation. 5 public Vector3 localEulerAngles { get { return localRotation.eulerAngles; } set { localRotation = Quaternion.Euler(value); } } 6

となっており、同じ処理と考えてよさそうです。

投稿2019/01/29 20:31

Bongo

総合スコア10816

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

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

退会済みユーザー

退会済みユーザー

2019/01/30 15:28

ご回答ありがとうございます。 明確な根拠を教えていただきありがとうございます。 解決しました。 すみません、あともう1点質問させていただけませんか? 以前にBongo様から、 transform.Rotate(X, Y, Z); transform.localRotation *= Quaternion.Euler(X, Y, Z); が同じ処理であることを教わったのですが、 もしかしたら、 transform.Rotate(X, Y, Z, Space.World); transform.rotation *= Quaternion.Euler(X, Y, Z); も同じ処理かもしれないと思って、 https://github.com/Unity-Technologies/UnityCsReference/blob/master/Runtime/Transform/ScriptBindings/Transform.bindings.cs を調べたのですが、 public void Rotate(Vector3 eulers, [UnityEngine.Internal.DefaultValue("Space.Self")] Space relativeTo) { Quaternion eulerRot = Quaternion.Euler(eulers.x, eulers.y, eulers.z); if (relativeTo == Space.Self) localRotation = localRotation * eulerRot; else { rotation = rotation * (Quaternion.Inverse(rotation) * eulerRot * rotation); } } で、elseの方では、 rotation = rotation * eulerRot; とは書かれてなかったので、 下記は同じ処理ではないということでしょうか? transform.Rotate(X, Y, Z, Space.World); transform.rotation *= Quaternion.Euler(X, Y, Z);
Bongo

2019/01/30 23:00

そうですね。 transform.rotation *= Quaternion.Euler(X, Y, Z); は transform.rotation = transform.rotation * Quaternion.Euler(X, Y, Z); の形になります。一方、 rotation = rotation * (Quaternion.Inverse(rotation) * eulerRot * rotation); は、式の上では結合順序を変えても結果は変わらないはずなので、カッコの位置を変えて rotation = (rotation * Quaternion.Inverse(rotation)) * eulerRot * rotation; と変形でき、(rotation * Quaternion.Inverse(rotation))はQuaternion.identityに置き換えられるので rotation = Quaternion.identity * eulerRot * rotation; となり、Quaternion.identityは別のクォータニオンとかけても影響を及ぼさないので rotation = eulerRot * rotation; の形になります。transform.rotationとQuaternion.Euler(X, Y, Z)の左右が逆転していますので、結果も異なるというわけですね。 Unityのコードが、なぜrotation = eulerRot * rotation;ではなくrotation = rotation * (Quaternion.Inverse(rotation) * eulerRot * rotation);になっているのかについては理由を見つけることができませんでした。 両者は数学的には同等のはずですが、コンピュータ上の計算では誤差の出かたが違ってくるはずです。 ランダムな2つの回転を各方法で合成するというのを約10億回行ったところ、結果のx、y、z、wにはおよそ0.001~0.05程度のずれが生じました。 あくまでも想像ですが、昔のバージョンでは回転の計算が「*=」を使う形に統一されていて rotation *= Quaternion.Inverse(rotation) * eulerRot * rotation; だったけれども、のちに社内のルールとして「回転計算で*=を使うと順序が分かりづらくなるので使わない」なんて方針になり、今の形になったのかもしれません。 そのときrotation = eulerRot * rotation;の形に変えなかったのは、誤差の出かたを旧バージョンと同じにしようとしてのことだった...という説はいかがでしょうか? 1回の計算で発生するずれはごくわずかですが、長時間アニメーションを続けるようなスクリプトだと多少の影響はあるでしょう。もしここをrotation = eulerRot * rotation;の形にしていたら、ユーザから「Unityのバージョンを上げたら、スクリプトのコードを変えていないのに動きがちょっと変わった」などと苦情が来たかもしれません。 公開されているコードはバージョン2017までで、そこではすでに回転部分のコードは今の形になっていましたので、それ以前は実際のところどうだったのかはわかりませんでした。まあ、大した違いではないのであまり拘泥せず「そういうものだ」と思って深く立ち入らない方がいいんじゃないでしょうか?
退会済みユーザー

退会済みユーザー

2019/01/31 02:54 編集

ご回答ありがとうございます。 すみません、自分の理解力に自信がなくて念の為確認させていただきたいのですが、 下記2行は同じ処理ではないということですね? transform.Rotate(X, Y, Z, Space.World); transform.rotation *= Quaternion.Euler(X, Y, Z); そして、細かい誤差を考慮しなければ、下記2行が同じ処理ということですね? transform.Rotate(X, Y, Z, Space.World); transform.rotation = Quaternion.Euler(X, Y, Z) * transform.rotation;  (rotation * Quaternion.Inverse(rotation))はQuaternion.identityと同じなんですね。 勉強になります。rotationに逆回転のrotationを掛ければ無回転になるということですね。 誤差のご解説、ご検証ありがとうございます。 ご教示いただいた通り、rotation = eulerRot * rotation;ではなくrotation = rotation * (Quaternion.Inverse(rotation) * eulerRot * rotation);になっているのかについては気にしないことにします。
Bongo

2019/01/31 03:38

はい、長々と書いてしまいすみませんが、結論としてはそういうことです。
退会済みユーザー

退会済みユーザー

2019/01/31 08:21

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問