Local and World Coordinate Systems

Learn the difference between local and world coordinate systems in Unity. Covers transform.position, transform.localPosition, coordinate conversion, and more.

What is a Coordinate System?

A coordinate system is a reference for expressing an object's position. Unity uses two coordinate systems: World Space and Local Space. Understanding the difference between them allows you to move and place objects accurately.

Basic Concepts

  • World Space: Absolute position in the entire scene (reference shared by all objects)
  • Local Space: Relative position based on parent object (affected by parent's rotation/movement)
  • Coordinate Conversion: Converting between local ↔ world coordinates

World Space

transform.position

using UnityEngine;

public class WorldPosition : MonoBehaviour
{
    void Start()
    {
        // Position in world space (absolute position)
        Vector3 worldPos = transform.position;
        
        Debug.Log($"World position: {worldPos}");
        
        // Set directly in world coordinates
        transform.position = new Vector3(5, 0, 3);
    }
}

Characteristics:

  • Absolute position in the entire scene
  • Independent of parent object's position/rotation
  • All objects use the same reference

World Space Example

using UnityEngine;

public class WorldSpaceExample : MonoBehaviour
{
    public Transform target;
    
    void Update()
    {
        // Move in world coordinates
        transform.position = new Vector3(0, 0, 0);  // Scene origin
        
        // Calculate distance in world coordinates
        if (target != null)
        {
            float distance = Vector3.Distance(transform.position, target.position);
            Debug.Log($"World coordinate distance: {distance}");
        }
    }
}

Local Space

transform.localPosition

using UnityEngine;

public class LocalPosition : MonoBehaviour
{
    void Start()
    {
        // Position in local space (relative to parent)
        Vector3 localPos = transform.localPosition;
        
        Debug.Log($"Local position: {localPos}");
        
        // Set directly in local coordinates
        transform.localPosition = new Vector3(1, 0, 0);
    }
}

Characteristics:

  • Relative position based on parent object
  • Local coordinate axes rotate when parent rotates
  • Local coordinate origin moves when parent moves

Local Space Example

using UnityEngine;

public class LocalSpaceExample : MonoBehaviour
{
    void Start()
    {
        // Move 2 units to the right relative to parent
        transform.localPosition = new Vector3(2, 0, 0);
        
        // When parent rotates, local coordinate axes also rotate
        // When parent moves, local coordinate origin also moves
    }
}

World vs Local Coordinates Comparison

Basic Comparison

using UnityEngine;

public class CoordinateComparison : MonoBehaviour
{
    void Start()
    {
        // World coordinates (absolute position)
        Vector3 worldPos = transform.position;
        Debug.Log($"World coordinates: {worldPos}");
        
        // Local coordinates (relative to parent)
        Vector3 localPos = transform.localPosition;
        Debug.Log($"Local coordinates: {localPos}");
        
        // Values may differ when parent exists
        // Values are the same when no parent exists
    }
}

Difference When Parent Exists

using UnityEngine;

public class ParentChildExample : MonoBehaviour
{
    public Transform parentObject;
    
    void Start()
    {
        // Create child object
        GameObject child = new GameObject("Child");
        child.transform.SetParent(parentObject);
        
        // Set in local coordinates (relative to parent)
        child.transform.localPosition = new Vector3(1, 0, 0);
        
        // If parent is at (5, 0, 0)
        // Child's world coordinates become (6, 0, 0)
        
        Debug.Log($"Child local coordinates: {child.transform.localPosition}");
        Debug.Log($"Child world coordinates: {child.transform.position}");
    }
}

Coordinate Conversion

Local → World Conversion

using UnityEngine;

public class LocalToWorld : MonoBehaviour
{
    void Start()
    {
        // Local coordinates
        Vector3 localPos = new Vector3(1, 0, 0);
        
        // Convert local to world coordinates
        Vector3 worldPos = transform.TransformPoint(localPos);
        
        Debug.Log($"Local coordinates: {localPos}");
        Debug.Log($"World coordinates: {worldPos}");
    }
}

World → Local Conversion

using UnityEngine;

public class WorldToLocal : MonoBehaviour
{
    void Start()
    {
        // World coordinates
        Vector3 worldPos = new Vector3(5, 0, 3);
        
        // Convert world to local coordinates
        Vector3 localPos = transform.InverseTransformPoint(worldPos);
        
        Debug.Log($"World coordinates: {worldPos}");
        Debug.Log($"Local coordinates: {localPos}");
    }
}

TransformPoint() vs InverseTransformPoint()

using UnityEngine;

public class TransformPointExample : MonoBehaviour
{
    void Start()
    {
        Vector3 localPos = new Vector3(1, 0, 0);
        
        // Local → World conversion
        Vector3 worldPos = transform.TransformPoint(localPos);
        
        // World → Local conversion (inverse)
        Vector3 backToLocal = transform.InverseTransformPoint(worldPos);
        
        // Should be same as original value
        Debug.Log($"Original local: {localPos}");
        Debug.Log($"Converted world: {worldPos}");
        Debug.Log($"Back to local: {backToLocal}");
    }
}

Direction Vector Conversion

TransformDirection() - Direction Vector Conversion

using UnityEngine;

public class TransformDirection : MonoBehaviour
{
    void Start()
    {
        // Local direction vector (direction, not position)
        Vector3 localDirection = Vector3.forward;  // Local Z-axis direction
        
        // Convert local direction to world direction
        Vector3 worldDirection = transform.TransformDirection(localDirection);
        
        Debug.Log($"Local direction: {localDirection}");
        Debug.Log($"World direction: {worldDirection}");
    }
}

InverseTransformDirection() - Inverse Direction Conversion

using UnityEngine;

public class InverseTransformDirection : MonoBehaviour
{
    void Start()
    {
        // World direction vector
        Vector3 worldDirection = Vector3.forward;
        
        // Convert world direction to local direction
        Vector3 localDirection = transform.InverseTransformDirection(worldDirection);
        
        Debug.Log($"World direction: {worldDirection}");
        Debug.Log($"Local direction: {localDirection}");
    }
}

Practical Usage Examples

Example 1: Placing Child Relative to Parent

using UnityEngine;

public class ChildPlacement : MonoBehaviour
{
    public GameObject childPrefab;
    
    void Start()
    {
        // Create child object
        GameObject child = Instantiate(childPrefab);
        child.transform.SetParent(transform);
        
        // Place 2 units to the right relative to parent (local coordinates)
        child.transform.localPosition = new Vector3(2, 0, 0);
        
        // Child maintains position relative to parent even when parent rotates/moves
    }
}

Example 2: Setting Absolute Position in World Coordinates

using UnityEngine;

public class AbsolutePosition : MonoBehaviour
{
    void Start()
    {
        // Place at specific position in scene (world coordinates)
        transform.position = new Vector3(10, 0, 5);
        
        // World coordinates are absolute even with parent
        // Object stays at (10, 0, 5) even if parent moves
    }
}

Example 3: Effect of Parent Rotation on Local Coordinates

using UnityEngine;

public class RotationEffect : MonoBehaviour
{
    public Transform parent;
    public Transform child;
    
    void Start()
    {
        // Set child as parent's child
        child.SetParent(parent);
        
        // Place in local coordinates (right relative to parent)
        child.localPosition = new Vector3(2, 0, 0);
        
        // Rotate parent 90 degrees
        parent.Rotate(0, 90, 0);
        
        // Child's local coordinates don't change but
        // world coordinates change according to parent's rotation
        Debug.Log($"Child local coordinates: {child.localPosition}");
        Debug.Log($"Child world coordinates: {child.position}");
    }
}

Example 4: Placing Camera Relative to Player

using UnityEngine;

public class CameraFollow : MonoBehaviour
{
    public Transform player;
    public Vector3 offset = new Vector3(0, 5, -10);
    
    void LateUpdate()
    {
        // Place camera based on player's world coordinates
        transform.position = player.position + offset;
        
        // Or use local coordinates (set camera as player's child)
        // transform.localPosition = offset;
    }
}

Example 5: Distance Calculation in World Coordinates

using UnityEngine;

public class DistanceCalculation : MonoBehaviour
{
    public Transform target1;
    public Transform target2;
    
    void Update()
    {
        // Calculate distance in world coordinates
        float distance = Vector3.Distance(target1.position, target2.position);
        
        Debug.Log($"Distance between objects: {distance}");
        
        // Cannot calculate distance in local coordinates (references may differ)
    }
}

transform.Translate() and Coordinate Systems

Translate() Coordinate System Options

using UnityEngine;

public class TranslateSpace : MonoBehaviour
{
    void Update()
    {
        // Space.World: Move relative to world coordinate system
        transform.Translate(1, 0, 0, Space.World);
        
        // Space.Self: Move relative to local coordinate system (default)
        transform.Translate(1, 0, 0, Space.Self);
        // Or
        transform.Translate(1, 0, 0);  // Default is Space.Self
    }
}

World Space Movement vs Local Space Movement

using UnityEngine;

public class TranslateComparison : MonoBehaviour
{
    void Update()
    {
        // Method 1: World space (independent of rotation)
        if (Input.GetKey(KeyCode.W))
        {
            transform.Translate(0, 0, 1 * Time.deltaTime, Space.World);
        }
        
        // Method 2: Local space (direction changes with rotation)
        if (Input.GetKey(KeyCode.S))
        {
            transform.Translate(0, 0, -1 * Time.deltaTime, Space.Self);
        }
    }
}

Notes

  1. When no parent: position and localPosition have the same value
  2. When parent exists: position is world coordinates, localPosition is relative to parent
  3. Effect of rotation: When parent rotates, local coordinate axes also rotate, changing direction
  4. Effect of movement: When parent moves, local coordinate origin also moves

Practical Tips

Tip 1: When to Use Local Coordinates

using UnityEngine;

public class WhenToUseLocal : MonoBehaviour
{
    // Use local coordinates when:
    // 1. Placing child relative to parent
    // 2. Child should move/rotate with parent
    // 3. Placing UI elements relative to parent panel
    
    void SetupUI()
    {
        GameObject button = new GameObject("Button");
        button.transform.SetParent(transform);
        
        // Place relative to parent panel (local coordinates)
        button.transform.localPosition = new Vector3(100, -50, 0);
    }
}

Tip 2: When to Use World Coordinates

using UnityEngine;

public class WhenToUseWorld : MonoBehaviour
{
    // Use world coordinates when:
    // 1. Placing at absolute position in scene
    // 2. Calculating distance to other objects
    // 3. Position must be maintained regardless of parent
    
    void SpawnEnemy()
    {
        GameObject enemy = new GameObject("Enemy");
        
        // Place at specific position in scene (world coordinates)
        enemy.transform.position = new Vector3(10, 0, 5);
        
        // Calculate distance to player
        float distance = Vector3.Distance(
            enemy.transform.position,
            transform.position
        );
    }
}

Tip 3: Using Coordinate Conversion

using UnityEngine;

public class CoordinateConversion : MonoBehaviour
{
    public Transform target;
    
    void Update()
    {
        // Convert target's world coordinates to my local coordinates
        Vector3 localTargetPos = transform.InverseTransformPoint(target.position);
        
        // Check which direction target is in my local coordinate system
        if (localTargetPos.x > 0)
        {
            Debug.Log("Target is on the right");
        }
        else if (localTargetPos.x < 0)
        {
            Debug.Log("Target is on the left");
        }
    }
}

← Back to Table of Contents