Unityのtransform.rotationとlocalRotationの違い|世界から見た向きと親から見た向き
- 1. 今回もWallとBulletHoleで考える
- 2. transform.rotationとは?
- 3. transform.localRotationとは?
- 4. まず単純な状態で考える
- 5. Wallを90度回転させる
- 6. でもlocalRotationは変わらない
- 7. positionとの関係と同じ
- 8. 図で考えてみる
- 9. 実際にConsoleへ表示してみよう
- 10. たとえば最初は
- 11. Wallを90度回転したあと
- 12. localRotationを0にするとどうなる?
- 13. rotationをidentityにすると意味が違う
- 14. 同じidentityでも意味が違う
- 15. rotationとlocalRotationを整理する
- 16. BulletHoleではどちらが重要?
- 17. 最初の向きはhit.normalから作っていた
- 18. そのあと親にしていた
- 19. ここが非常に重要
- 20. 実験コード
- 21. 親を回転させて確認する
- 22. localRotationはQuaternion
- 23. Euler角で考えすぎない
- 24. 親がない場合は?
- 25. 親子関係があると違いが重要になる
- 26. rotationを使う場面
- 27. localRotationを使う場面
- 28. positionとの対応で覚える
- 29. 「local」が付いたら親基準
- 30. 今回の流れを整理する
- 31. まとめ
今回もWallとBulletHoleで考える
前回は、
transform.position
transform.localPosition
の違いを学びました。
ポイントは、
position
= 世界から見た位置
localPosition
= 親から見た位置
でした。
今回は、その「回転版」です。
扱うのは、
transform.rotation
と、
transform.localRotation
です。
前回と同じように、
Wall
└ BulletHole
という親子関係があるとします。
BulletHoleは、
bulletHole.transform.SetParent(
hit.collider.transform,
true
);
によってWallの子になっています。
そのため、Wallが回転するとBulletHoleも一緒に回ります。
ここで、
BulletHole自身の回転はどう表されているのか?
を考えてみましょう。

transform.rotationとは?
まず、
transform.rotation
です。
これは、
世界全体から見たGameObjectの向き
を表します。
つまり、
ワールド座標系から見て
どちらを向いているか
という情報です。
transform.localRotationとは?
一方、
transform.localRotation
は、
親Transformから見た相対的な向き
です。
今回なら、
Wallから見て
BulletHoleがどちらを向いているか
を表します。
つまり、
rotation
= 世界から見た向き
localRotation
= 親から見た向き
です。
まず単純な状態で考える
たとえばWallが回転していないとします。
Wall
Rotation = 0°
└ BulletHole
BulletHoleもWallと同じ方向を向いているなら、
BulletHole.rotation
= 0°
BulletHole.localRotation
= 0°
と考えられます。
この段階では、
rotation
localRotation
の違いが分かりにくいかもしれません。
そこでWallを回転させてみます。

Wallを90度回転させる
WallをY軸方向へ90度回転したとします。
Wall
Rotation Y = 90°
BulletHoleはWallの子なので、
一緒に90度回転します。
世界から見るとBulletHoleも、
Y = 90°
の方向を向きます。
そのため、
bulletHole.transform.rotation
は、世界から見て90度回転した状態になります。

でもlocalRotationは変わらない
ここが重要です。
WallとBulletHoleの向きの関係が、
Wallの面に対して
BulletHoleは正面を向いている
ままなら、
bulletHole.transform.localRotation
は変わりません。
つまり、
Wallを回転
↓
BulletHoleも一緒に回転
↓
世界から見た向きは変わる
↓
親から見た向きは同じ
となります。
positionとの関係と同じ
前回は、
親が移動する
↓
positionは変わる
localPositionは変わらない
でした。
今回は、
親が回転する
↓
rotationは変わる
localRotationは変わらない
です。
考え方はほとんど同じです。
図で考えてみる
最初は、
世界
↑
Wall
└ BulletHole
で、どちらも正面を向いているとします。
その後、Wallを右へ90度回転します。
世界
→
Wall
└ BulletHole
BulletHoleも一緒に右を向きます。
世界から見れば、
向きが変わった
ので rotation は変わります。
しかしWallから見れば、
BulletHoleはWallに対して
同じ向きのまま
なので localRotation は変わりません。

実際にConsoleへ表示してみよう
BulletHoleを生成したあと、
Debug.Log(
"rotation = "
+ bulletHole.transform.rotation.eulerAngles
);
Debug.Log(
"localRotation = "
+ bulletHole.transform.localRotation.eulerAngles
);
としてみましょう。
Quaternion のままだと初心者には見づらいので、
.eulerAngles
を付けて、
X
Y
Z
の角度として表示すると分かりやすくなります。
たとえば最初は
Wallが回転していない状態なら、
rotation
(0, 0, 0)
localRotation
(0, 0, 0)
のようになるかもしれません。
Wallを90度回転したあと
WallをY軸に90度回転すると、
BulletHoleの、
rotation
は、
(0, 90, 0)
のように変わります。
一方、
localRotation
は、
(0, 0, 0)
のままになることがあります。
つまり、
世界から見ると90度回った
親から見ると向きは変わっていない
ということです。

localRotationを0にするとどうなる?
では、
bulletHole.transform.localRotation =
Quaternion.identity;
としてみましょう。
Quaternion.identity は、
回転なし
を表します。
ただし、
世界から見て回転なし
ではありません。
ここが大切です。
localRotation に対して設定しているので、
親から見て回転なし
という意味になります。
つまりBulletHoleは、
親Wallと同じ向き
になります。

rotationをidentityにすると意味が違う
一方、
bulletHole.transform.rotation =
Quaternion.identity;
とすると、
BulletHoleは、
世界から見て回転なし
になります。
つまり、
世界の基準方向
へ向きます。
Wallが90度回転していたとしても、
BulletHoleだけ世界基準の方向へ戻ることになります。

同じidentityでも意味が違う
transform.rotation =
Quaternion.identity;
は、
世界基準で回転なし
です。
一方、
transform.localRotation =
Quaternion.identity;
は、
親基準で回転なし
です。
前回の、
position = Vector3.zero
localPosition = Vector3.zero
と同じ考え方です。
rotationとlocalRotationを整理する
| プロパティ | 基準 |
|---|---|
transform.rotation |
世界全体 |
transform.localRotation |
親Transform |
一言で言えば、
rotation
→ 世界から見た向き
localRotation
→ 親から見た向き
です。

BulletHoleではどちらが重要?
今回のBulletHoleは、
Wall
└ BulletHole
という関係です。
弾痕にとって重要なのは、
世界のどちらを向いているか
よりも、
Wallに対してどちらを向いているか
です。
なぜならWallが回転しても、
弾痕はWallに貼り付いた状態を保つ必要があるからです。
その意味では、
localRotation
の考え方が非常に重要です。
最初の向きはhit.normalから作っていた
ここで前の記事ともつながります。
弾痕の生成時には、
Quaternion rotation =
Quaternion.LookRotation(
hit.normal
);
としていました。
これは、
当たった面の方向
↓
世界空間上の回転
を作っています。
そのあと、
Instantiate(
bulletHolePrefab,
position,
rotation
);
で、まず正しいワールド回転で弾痕を生成しています。
そのあと親にしていた
次に、
bulletHole.transform.SetParent(
hit.collider.transform,
true
);
としていました。
true なので、
現在のワールド位置・回転を保つ
ように親が変更されます。
つまり、
まず世界基準で正しい向きにする
↓
その見た目を保ったまま
Wallの子にする
↓
localRotationが自動的に決まる
という流れです。
ここが非常に重要
生成時は、
rotation
というワールド回転を使っています。
親にしたあとでは、
localRotation
として、
Wallとの相対的な向きが保持されます。
つまり、
生成時
→ 世界基準
親子関係を作った後
→ 親基準の関係も持つ
ということです。
実験コード
次のようにすると、
rotation
と、
localRotation
を比較できます。
using UnityEngine;
using UnityEngine.InputSystem;
public class BulletHoleShooter : MonoBehaviour
{
[SerializeField]
GameObject bulletHolePrefab;
void Update()
{
if (Mouse.current.leftButton.wasPressedThisFrame)
{
Ray ray =
Camera.main.ScreenPointToRay(
Mouse.current.position.value
);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
Vector3 position =
hit.point
+ hit.normal * 0.01f;
Quaternion rotation =
Quaternion.LookRotation(
hit.normal
);
GameObject bulletHole =
Instantiate(
bulletHolePrefab,
position,
rotation
);
bulletHole.transform.SetParent(
hit.collider.transform,
true
);
Debug.Log(
"rotation = "
+ bulletHole.transform
.rotation.eulerAngles
);
Debug.Log(
"localRotation = "
+ bulletHole.transform
.localRotation.eulerAngles
);
}
}
}
}
Wallを回転させながら値を見ると、
違いが分かりやすくなります。
親を回転させて確認する
たとえば、
Wallの回転を、
Y = 0°
から、
Y = 90°
へ変更してみます。
すると、
BulletHoleの、
rotation
は変化します。
しかしWallとの相対的な向きが変わっていなければ、
localRotation
は基本的に同じままです。
これが、
子オブジェクトが親の回転についていく仕組み
です。
localRotationはQuaternion
注意点として、
transform.localRotation
の型は、
Quaternion
です。
transform.rotation
も同じく、
Quaternion
です。
つまり、
rotation
localRotation
の違いは、
型の違いではありません。
どちらもQuaternionです。
違うのは、
基準となる座標系
です。
Euler角で考えすぎない
Inspectorでは、
X
Y
Z
の角度が見えるため、
回転を、
0°
90°
180°
のように考えがちです。
しかしUnity内部では、
Quaternion
として回転を扱っています。
今回、
.eulerAngles
を使うのは、
確認しやすく表示するため
です。
回転そのものはQuaternionとして扱われている、
という点は覚えておきましょう。
親がない場合は?
GameObjectに親がない場合、
親基準
=
世界基準
になります。
そのため、
transform.rotation
と、
transform.localRotation
は同じ回転を表します。
これは、
position
localPosition
の場合と同じです。
親子関係があると違いが重要になる
たとえば、
Player
└ Weapon
なら、
weapon.transform.localRotation
は、
Playerから見てWeaponがどちらを向いているか
を表します。
Car
└ Camera
なら、
Carから見てCameraがどちらを向いているか
です。
今回なら、
Wall
└ BulletHole
なので、
Wallから見てBulletHoleがどちらを向いているか
になります。
rotationを使う場面
たとえば、
世界の北方向へ向ける
特定のワールド方向へ向ける
hit.normalの方向へ向ける
など、
世界基準の向き
を扱いたい場合には、
transform.rotation
が分かりやすいでしょう。
localRotationを使う場面
一方、
武器をPlayerに対して少し傾ける
CameraをCarに対して向ける
子パーツを親から見て回転させる
など、
親との向きの関係
を扱いたい場合には、
transform.localRotation
が重要になります。
positionとの対応で覚える
4つをまとめると、非常に分かりやすくなります。
| プロパティ | 意味 |
|---|---|
position |
世界から見た位置 |
localPosition |
親から見た位置 |
rotation |
世界から見た向き |
localRotation |
親から見た向き |
つまり、
position
rotation
↓
ワールド基準
localPosition
localRotation
↓
親基準
です。
「local」が付いたら親基準
初心者のうちは、
local
という言葉に注目すると覚えやすいでしょう。
localPosition
なら、
親から見た位置
localRotation
なら、
親から見た回転
です。
逆に、
position
rotation
は、
世界基準
と考えると整理しやすくなります。
今回の流れを整理する
これまでの記事をつなげると、
Raycast
↓
hit.point
↓
ワールド位置を取得
hit.normal
↓
ワールド方向を取得
Instantiate
↓
ワールド位置・回転で弾痕を作る
SetParent
↓
Wallの子にする
localPosition
↓
Wallから見た位置
localRotation
↓
Wallから見た向き
となります。
最初はRaycastの話でしたが、
ここまで進むと、
UnityのTransformと座標系の考え方
まで自然につながってきます。
まとめ
transform.rotation
は、
世界全体から見たGameObjectの回転
です。
transform.localRotation
は、
親Transformから見た相対的な回転
です。
親Wallを回転させると、
BulletHole.rotation
↓
世界から見た向きなので変わる
BulletHole.localRotation
↓
親との向きが同じなら変わらない
となります。
前回の位置と並べて覚えると、
position
= 世界から見た位置
localPosition
= 親から見た位置
rotation
= 世界から見た向き
localRotation
= 親から見た向き
です。
つまり、
local が付いていないものはワールド基準、local が付いているものは親基準
と整理すると、UnityのTransformがかなり理解しやすくなります。
【シリーズ】Raycastで弾痕を作りながら学ぶ(7/9)
← 前の記事:positionとlocalPositionの違い | シリーズ目次 | 次の記事:localScaleとlossyScaleの違い →








ディスカッション
コメント一覧
まだ、コメントがありません