Transformが持つpositionとlocalPosition、簡単な状況だとわかっていても、入れ子になったり、それぞれのScaleが異なったりするとだんだん混乱してきませんか?ちょっとしたクイズ形式にしたので考えてみてください。
問題
ぞれぞれScaleが10、5、1のCubeを3つ(Cube10、Cube5、Cube1)作って、Hierarchy上で入れ子構造にして、
Cube5、Cube1のInspector上でPosition(LocalPosition)のzを1に変更します。
さて、このときのCube1のWorldPosition(Cube1.transfrom.position)のzはいくつでしょうか?
答え
答え・・・の前に計算方法です。
先に答えだと問題を読んでいる途中で、答えまで目に入っってしまうかなと思い、この構成になっています。
特に理由は要らず答えという方は一番下までスクロールしてください。
計算方法
UnityEditorのInspectorに表示されているものは、localの値なので、それぞれworld座標に変換していきます。
Cube5
まずCube5のWorldPositionを考えます。Cube5のWorldPositionは、Cube5のlocalPosition.zと親のCube10のlossyScale.zの積になります。今回の場合は1.0*10.0=10なので、10です。
Cube1
次にCube1のWorldPositionを考えます。Cube1のWorldPositionは、Cube1のlocalPosition.zと親のCube5のlossyScale.zの積にCube5のWolrdPosition.zを足したものになります。今回の場合は1.0*5.0+10=15なので、15です。
本当に答え
15です。
補足
それぞれDebugログでzのpositionとscaleを出してみるとこんな感じになります。UnityEditorのInspectorで表示されている値がlocalであることがわかりますね。
-- Cube10 --
World(pos, scale): 0.0, 10.0
Local(pos, scale): 0.0, 10.0
-- Cube5 --
World(pos, scale): 10.0, 5.0
Local(pos, scale): 1.0, 0.5
-- Cube1 --
World(pos, scale): 15.0, 1.0
Local(pos, scale): 1.0, 0.2
サンプルプログラム
GitHubにプログラム、シーンなどを含め、あげてあります。良かったら手元で動かして試してみてください。
ログの処理の抜粋
using UnityEngine;
public class PosScaleTest : MonoBehaviour
{
[SerializeField] private GameObject cube10;
[SerializeField] private GameObject cube5;
[SerializeField] private GameObject cube1;
void Start()
{
Log(cube10.transform);
Log(cube5.transform);
Log(cube1.transform);
}
private void Log(Transform trn)
{
Debug.Log($"-- {trn.gameObject.name} --");
Debug.Log($"World(pos, scale): {trn.position.z:F1}, {trn.lossyScale.z:F1}");
Debug.Log($"Local(pos, scale): {trn.localPosition.z:F1}, {trn.localScale.z:F1}");
}
}