teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

2

インスペクタ上の回転表示について追記

2017/12/10 07:50

投稿

Bongo
Bongo

スコア10816

answer CHANGED
@@ -81,4 +81,43 @@
81
81
 
82
82
  途中のインスペクタの表示ではやはりx、y、zが一斉に変化しており、回転が狂ってしまっているように見えるかもしれませんが、ちゃんと等価な回転になっており、12回の回転で元の向きに戻ります。
83
83
 
84
- ![プレビュー3](fa50f7c9288e5386125ff1d062254599.gif)
84
+ ![プレビュー3](fa50f7c9288e5386125ff1d062254599.gif)
85
+
86
+ [追記]
87
+ エディタ上だとRotationに値を入れると(たとえ±360°を超えるようなものでも)、インスペクタを表示しなおしても勝手に変な値に書き換わることなく、その値が維持されるようです。編集する上では直感的で便利な機能だと思いますが、どうやらUnityは内部的にユーザが入力した、あるいはエディタ上で回転させたオイラー角をクォータニオンを経由させず、そのままの状態で保管しているみたいですね。
88
+ [How are Editor Transform.Rotation values calculated? : Unity3D](https://www.reddit.com/r/Unity3D/comments/5vy0om/how_are_editor_transformrotation_values_calculated/)を参考に下記のようにしてみると、インスペクタ上に表示されているのと同じ値を見ることができました。
89
+
90
+ ```C#
91
+ using UnityEngine;
92
+
93
+ [ExecuteInEditMode]
94
+ public class TestScript : MonoBehaviour
95
+ {
96
+ private Vector3 localEuler;
97
+
98
+ private void Start()
99
+ {
100
+ this.localEuler = transform.localEulerAngles;
101
+ #if UNITY_EDITOR
102
+ var serializedObject = new UnityEditor.SerializedObject(transform);
103
+ var serializedEulerHint = serializedObject.FindProperty("m_LocalEulerAnglesHint");
104
+ Debug.Log(serializedEulerHint.vector3Value);
105
+ #endif
106
+ }
107
+
108
+ private void Update()
109
+ {
110
+ if (Input.GetKeyDown(KeyCode.Space))
111
+ {
112
+ this.localEuler.x += 10;
113
+ this.localEuler.y += 10;
114
+ this.localEuler.z += 10;
115
+ transform.localEulerAngles = this.localEuler;
116
+ }
117
+ }
118
+ }
119
+ ```
120
+
121
+ ![インスペクタの回転表示](a025b08c58ff9aa5509b20afb860c138.png)
122
+
123
+ 実際の実行時には使えないでしょうが、エディタスクリプトでインスペクタ上の角度を意図通りに加減算させたいというようなことがあれば、このあたりをいじることになりそうです。

1

コメントを受けて追記

2017/12/10 07:49

投稿

Bongo
Bongo

スコア10816

answer CHANGED
@@ -22,4 +22,63 @@
22
22
 
23
23
  また、`transform.Rotate(0.0f, 30.0f, 0.0f, Space.World);`に変えてみると、今度はワールド座標の3軸周りに回転し、こちらもやはりインスペクタへの加減算とは微妙に異なるはずです(オブジェクトを別のオブジェクトの子にして、親オブジェクトもあらかじめ適当に傾けておくと違いが明確になるでしょう)。
24
24
 
25
- ![World](31fb67d3f1bbe9edeaeeb17851f42bc7.gif)
25
+ ![World](31fb67d3f1bbe9edeaeeb17851f42bc7.gif)
26
+
27
+ [コメントを受けて追記]
28
+ [localEulerAngles](https://docs.unity3d.com/ScriptReference/Transform-localEulerAngles.html)を取得して値を加減算し、ふたたびlocalEulerAnglesに書き戻す手が考えられるかと思います。
29
+
30
+ ```C#
31
+ using UnityEngine;
32
+
33
+ public class TestScript : MonoBehaviour
34
+ {
35
+ private void Update()
36
+ {
37
+ if (Input.GetKeyDown(KeyCode.Space))
38
+ {
39
+ var localEuler = transform.localEulerAngles;
40
+ localEuler.y += 30;
41
+ transform.localEulerAngles = localEuler;
42
+ }
43
+ }
44
+ }
45
+ ```
46
+
47
+ ![プレビュー1](44d48ac11de144b7b83ac7203f077334.gif)
48
+
49
+ ただし、リファレンスの注意書きにあるように、このようにすると意図通りにならない場合があります。たとえば上記の`localEuler.y += 30;`を`localEuler.x += 30;`にすると...
50
+
51
+ ![プレビュー2](80310798d984bbd8c6e8a05aa79991d0.gif)
52
+
53
+ Unity内部では回転をクォータニオンで持っており、オイラー角が必要になればそのクォータニオンからオイラー角が導出されますが、あるクォータニオンと同じ回転を表すオイラー角は一通りではないという特徴があるため、xだけを操作しているつもりなのにy、zも変化してしまい、最終的にめちゃくちゃな回転になってしまうかもしれません。
54
+
55
+ オイラー角からクォータニオンへ...の一方通行ならこの問題を回避できるかと思います。
56
+ コードをこのようにすると...
57
+
58
+ ```C#
59
+ using UnityEngine;
60
+
61
+ public class TestScript : MonoBehaviour
62
+ {
63
+ private Vector3 localEuler;
64
+
65
+ private void Start()
66
+ {
67
+ this.localEuler = transform.localEulerAngles;
68
+ }
69
+
70
+ private void Update()
71
+ {
72
+ if (Input.GetKeyDown(KeyCode.Space))
73
+ {
74
+ this.localEuler.x += 30;
75
+ transform.localEulerAngles = this.localEuler;
76
+ }
77
+ }
78
+ }
79
+
80
+ ```
81
+
82
+ 途中のインスペクタの表示ではやはりx、y、zが一斉に変化しており、回転が狂ってしまっているように見えるかもしれませんが、ちゃんと等価な回転になっており、12回の回転で元の向きに戻ります。
83
+
84
+ ![プレビュー3](fa50f7c9288e5386125ff1d062254599.gif)