【Unity】ワールド座標とローカル座標の相互変換

こじゃらこじゃら

ワールド座標とローカル座標を双方向で変換するにはどうすればいいの~?

このはこのは

Transformの座標系変換メソッドを使うのよ。

Unityではゲームオブジェクトの座標を扱うとき、ワールド座標ローカル座標という二種類の座標が登場します。

それぞれ座標系が異なります。座標系が異なる両者を足すなどの演算はできません。

座標系が異なる場合、どちらか一方をもう一方の座標系に合わせるために座標系の変換が必要になります。

ローカル座標をワールド座標に変換するときはTransform.TransformPoint()メソッドを、逆にワールド座標をローカル座標に変換するときはTransform.InverseTransformPoint()メソッドを使って実現できます。

// ローカル座標→ワールド座標
var worldPoint = transform.TransformPoint(localTarget);
// ワールド座標→ローカル座標
var localPoint = transform.InverseTransformPoint(worldTarget);

ただし、使用上において注意点があり、本記事ではこの辺を含めてワールド座標とローカル座標の相互変換について解説していきます。

UCL UCL

この作品はユニティちゃんライセンス条項の元に提供されています

スポンサーリンク

ワールド座標系とローカル座標系

ワールド座標系は、シーンの原点を基準とした座標系です。ワールド空間とも呼びます。原点位置、向き、スケールはシーンにおいて常に固定です。

ローカル座標系は、ある親オブジェクト位置、向き、スケールを基準とした座標系です。ローカル空間とも呼びます。

ローカル空間は、座標系の原点がシーンから見て変化しているように見えます。
そのため、ローカル座標は親オブジェクトを基準とした相対座標とも言えます。

親オブジェクトが存在しない場合は、ワールド空間とローカル空間は一致します。

ワールド空間とローカル空間は、座標系の原点、向き、スケールの基準をどこに取るかが異なります。

このはこのは

座標の表現方法はどちらも一緒だけど、意味が異なるので注意が必要だわ。紛らわしいので混同しないように気を付けて!

座標の変換

ここからは、座標をローカル座標からワールド座標に変換する方法、逆にワールド座標からローカル座標に変換する方法について解説していきます。

ローカル空間からワールド空間への変換

Transform.TransformPoint()メソッドを使います。
メソッドの形式は次の通りです。

public Vector3 TransformPoint(Vector3 position);

引数positionには、ワールド座標に変換したいローカル座標を指定します。

参考:Transform-TransformPoint – Unity スクリプトリファレンス

使用例は以下のようになります。

var worldPoint = transform.TransformPoint(localPoint);

ワールド空間からローカル空間への変換

Transform.InverseTransformPoint()メソッドを使います。
メソッドの形式は次の通りとなります。

public Vector3 InverseTransformPoint(Vector3 position);

引数positionには、変換したいワールド座標を指定します。

参考:Transform-InverseTransformPoint – Unity スクリプトリファレンス

使用例は以下の通りです。

var localPoint = transform.InverseTransformPoint(worldPoint);

ローカル座標は親から見た相対座標

ローカル座標は親オブジェクトを基準とした相対座標ですが、どれが親かを混同してしまいやすい部分です。

ローカル座標を取り扱う際の注意点について触れておきます。

ローカル座標からワールド座標に変換する場合

あるオブジェクトのローカル座標をワールド座標に変換することを例にとってみましょう。

オブジェクトAのTransformをself、オブジェクトAと同じ座標系のローカル座標をlocalPointとします。

このとき、localPointをワールド座標worldPointに変換する処理は次のようになります。

var worldPoint = self.parent != null ? self.parent.TransformPoint(localPoint) : localPoint;

selfの親に対してTransformPoint()メソッドを呼び出しています。

これは、localPointはオブジェクトAと同じ座標系であること、オブジェクトAの座標はその親オブジェクトから見た相対座標であるためです。

self.TransformPoint()と呼び出すと、オブジェクトAから見た相対座標すなわちオブジェクトAの子オブジェクトのローカル座標として変換処理を実施してしまいます。

オブジェクトAがルート(親が無い状態)にある場合、ローカル座標とワールド座標は等しくなるので、変換は行いません。

親が無い場合はself.parentがnullになるので、nullチェックを行っています。

逆に、オブジェクトAを親としたローカル座標とする場合は、次の処理で問題ありません。

var worldPoint = self.TransformPoint(localPoint);

ワールド座標からローカル座標に変換する場合

ワールド座標からローカル座標に変換する時も同様です。

var localPoint = self.parent != null ? self.parent.InverseTransformPoint(worldPoint) : worldPoint;

オブジェクトAを親としたローカル座標とする場合は、次の処理で問題ありません。

var localPoint = self.InverseTransformPoint(worldPoint);

ローカル座標を扱うときは、どの親オブジェクトに対する座標系なのかを強く意識しておくのが大切です。

さいごに

今回はワールド座標とローカル座標の相互変換について解説しました。

座標以外にも、ベクトルや向きをワールド空間・ローカル空間で相互に変換するためのメソッドも用意されています。

これらの使い方については、別記事で紹介させていただく予定です。

参考サイト

スポンサーリンク