Unity Transform.positionの使い方|座標の取得・変更・移動とlocalPositionの違い
Unityでオブジェクトの座標を取得・変更するには、transform.positionを使います。親を基準に指定したいときはlocalPosition、毎フレーム動かすときは移動量にTime.deltaTimeを掛ける、と分けて考えるとわかりやすくなります。
やりたいことから選ぶ
現在位置を読む → transform.position
指定位置へ一度で移す → positionへVector3を代入
一定速度で動かす → positionに「方向 × 速度 × deltaTime」を加算
親からの位置を読む・変える → localPosition
Unity 6.0の公式仕様をもとに、3DのCubeで試せる例を紹介します。位置・回転・大きさの全体像はTransformの基本とWorld・Localの違いも参考にしてください。
positionとlocalPositionの違い
positionはワールド空間の位置、localPositionは親のTransformを基準にした位置です。子オブジェクトのInspectorにあるPosition欄は、親から見たローカル座標を表示します。親がなければ両者は同じ値になります。
親と子の座標の例
親の位置:(-3, 0, -3)
子のlocalPosition:(0, 0, 0)
↓
子のposition:(-3, 0, -3)
子のlocalPositionを(2, 0, 0)にすると、子のpositionは(-1, 0, -3)になります。
※親の回転が(0, 0, 0)、Scaleが(1, 1, 1)の場合です。
ワールド座標だから親の影響を受けない、という意味ではありません。親を動かせば子のpositionも変わります。親の回転やScaleも、ローカル座標からワールド座標を計算するときに反映されます。localPositionは、オブジェクト自身の正面方向を表す値でもありません。
準備:親と子のCubeを用意する
- HierarchyでCreate Emptyを選び、Parentという空のGameObjectを作ります。Parentは他のオブジェクトの子にしません。
- ParentのPositionを(-3, 0, -3)、Rotationを(0, 0, 0)、Scaleを(1, 1, 1)にします。
- 3D Object → CubeでCubeを作り、HierarchyでParentの子にします。その後、CubeのInspectorのPositionを(0, 0, 0)に設定します。
- 以下の例は、ファイル名とクラス名をそろえて保存し、Cubeにアタッチします。移動用スクリプトは同時に複数有効にせず、1つずつ試してください。

現在の座標を取得する
PositionLogger.csをCubeに付けて再生すると、Consoleにワールド座標とローカル座標を1回ずつ表示します。
using UnityEngine;
public class PositionLogger : MonoBehaviour
{
private void Start()
{
Debug.Log("World: " + transform.position);
Debug.Log("Local: " + transform.localPosition);
}
}準備どおりの配置なら、Worldは(-3, 0, -3)、Localは(0, 0, 0)です。Xだけを読む場合はtransform.position.x、親から見たYだけならtransform.localPosition.yを使えます。
指定した座標へ移動する
PositionSetter.csは、再生開始時にCubeをワールド原点へ移す例です。positionへの代入はその位置へすぐに移す処理なので、移動途中のアニメーションは作りません。
using UnityEngine;
public class PositionSetter : MonoBehaviour
{
private void Start()
{
transform.position = Vector3.zero;
Debug.Log("World: " + transform.position);
Debug.Log("Local: " + transform.localPosition);
}
}Vector3.zeroはnew Vector3(0f, 0f, 0f)と同じ値です。好きな座標へ移す場合は、例えばnew Vector3(2f, 1f, -3f)を代入します。準備した親の位置が(-3, 0, -3)なら、ワールド原点へ移したCubeのlocalPositionは(3, 0, 3)になります。
親と同じ位置へ移したい場合は、transform.localPosition = Vector3.zeroとします。代入先がpositionかlocalPositionかで、基準が変わります。
Xだけを変更するには、一度取り出して戻す
transform.position.x = 2fのように直接書くと、C#のコンパイルエラーになります。positionから得るVector3は値型なので、変数へ取り出して変更し、positionへ戻します。次の3行はStartなどのメソッド内に書く例です。
Vector3 nextPosition = transform.position;
nextPosition.x = 2f;
transform.position = nextPosition;この方法ならYとZを維持できます。親を基準にXだけを変える場合は、取得と代入の両方をlocalPositionにそろえてください。
一定速度で移動する:+=とTime.deltaTime
WorldMover.csは、ワールドのXプラス方向へ毎秒2ユニット移動する例です。InspectorのSpeedで速さを調整できます。
using UnityEngine;
public class WorldMover : MonoBehaviour
{
[SerializeField] private float speed = 2f;
private void Update()
{
transform.position += Vector3.right * speed * Time.deltaTime;
}
}1フレームの移動量 = 方向 × 毎秒の速度 × 経過秒数
毎フレーム0.01だけ加算すると、30fpsでは毎秒0.3、60fpsでは毎秒0.6と速さが変わります。Time.deltaTimeを掛けると、フレーム間隔に合わせて移動量を調整できます。
+=は現在位置への加算、-=は減算です。1回だけ呼べば1回分だけ位置が変わり、Updateで繰り返せば連続した移動になります。毎フレームのDebug.LogはConsoleを埋めるので、座標確認は必要なときだけ行いましょう。
向いている方向へ移動する:Translate
ForwardMover.csは、オブジェクト自身の前方(ローカルZ方向)へ動かします。CubeのRotationのYを90にして、ワールドのZ方向への移動との違いを見てみましょう。
using UnityEngine;
public class ForwardMover : MonoBehaviour
{
[SerializeField] private float speed = 2f;
private void Update()
{
Vector3 step = Vector3.forward * speed * Time.deltaTime;
transform.Translate(step, Space.Self);
}
}Translateの第2引数を省略するとSpace.Selfです。Space.Worldにすると、オブジェクトの向きにかかわらずワールド軸を基準に移動します。position += Vector3.forward …はワールドのZ方向なので、Space.SelfのTranslateと常に同じ動きになるわけではありません。
Vector3.forwardやVector3.rightの値は、Vector3の座標・加算・正規化で詳しく紹介しています。
目的地で止める:MoveTowards
目標地点まで一定速度で進めたい場合は、Vector3.MoveTowardsが便利です。MoveToPoint.csを付け、InspectorのTarget Positionにワールド座標を設定します。
using UnityEngine;
public class MoveToPoint : MonoBehaviour
{
[SerializeField] private Vector3 targetPosition = new Vector3(3f, 0f, 0f);
[SerializeField, Min(0f)] private float speed = 2f;
private void Update()
{
float step = Mathf.Max(0f, speed) * Time.deltaTime;
transform.position = Vector3.MoveTowards(
transform.position, targetPosition, step);
}
}移動量が目的地までの距離を超える場合は目的地の値になるため、行き過ぎません。これは所要時間を指定する例ではなく、毎秒の速度で動かす例です。
位置が変わらない・戻るときの確認点
- Consoleにコンパイルエラーがなく、スクリプトとGameObjectが有効か確認します。ファイル名とクラス名も一致させます。
- positionとlocalPositionを混同していないか確認します。子のInspectorのPositionとワールド座標が違うのは正常です。
- 別のスクリプト、Animator、NavMeshAgentなどが同じ位置を書き換えていないか確認します。移動処理は1つに絞って試します。
- Time.timeScaleが0だと、deltaTimeを掛けた移動も止まります。ポーズ中の動作かどうかを確認します。
Rigidbodyで物理挙動を扱うオブジェクトは、Transformだけで移動させる例と分けて考えます。キネマティックなRigidbodyを連続移動させる場合は、FixedUpdateからMovePositionを使う方法があります。詳しくはRigidbodyでの移動方法を参照してください。
まとめ
まずはpositionで取得 → Vector3を代入して変更 → deltaTimeを掛けて連続移動の順に試してみましょう。親との位置関係はlocalPosition、自身の向きに沿う移動はTranslate、目的地で止める移動はMoveTowardsと使い分けると整理しやすくなります。
参考:Unity公式:position / localPosition / Translate / Time.deltaTime / MoveTowards / Microsoft:CS1612
サイトアイコン-2-150x150.png)