Ova

How to Rotate an Object to Look at Another Object in Unity?

Published in Unity Object Rotation 5 mins read

To rotate an object in Unity to face another object, the most straightforward methods involve using transform.LookAt() for simple cases or Quaternion.LookRotation() for more granular control, especially when needing to manage specific axes or achieve smooth transitions.

The Simplest Method: transform.LookAt()

The transform.LookAt() method is Unity's easiest way to make one GameObject orient itself towards another. It instantly rotates the calling object so that its forward (Z) axis points directly at the specified target.

How it Works:

You simply provide the target's Transform or Vector3 position. The object's Y-axis will typically align with the world's up direction, and its Z-axis will point at the target.

Example C# Code:

using UnityEngine;

public class LookAtTargetSimple : MonoBehaviour
{
    public Transform target; // Assign your target object in the Inspector

    void Update()
    {
        if (target != null)
        {
            transform.LookAt(target);
        }
    }
}
  • Pros:
    • Extremely simple to implement.
    • Instantly aligns the object.
  • Cons:
    • Can cause "flipping" if the target moves directly overhead or below.
    • Doesn't allow for easy axis locking (e.g., only rotating on the Y-axis).
    • Abrupt rotation; not suitable for smooth transitions without additional interpolation.

Advanced Control: Quaternion.LookRotation()

For situations requiring more precise control over the rotation, such as defining which way is "up" for the rotating object or interpolating the rotation smoothly, Quaternion.LookRotation() is the preferred choice.

How it Works:

Quaternion.LookRotation() takes a forward direction vector and an optional up direction vector. It calculates a Quaternion that, when applied to a Transform, makes its Z-axis point along the specified forward direction and its Y-axis point along the specified up direction.

The core idea is to define the vector pointing from your current object to the target object. This vector is computed as target.position - transform.position. This resulting vector represents the desired forward direction for your object. Quaternion.LookRotation then generates the precise rotation needed to align the object's forward axis with this calculated direction.

Example C# Code (Basic LookRotation):

using UnityEngine;

public class LookAtTargetAdvanced : MonoBehaviour
{
    public Transform target; // Assign your target object in the Inspector

    void Update()
    {
        if (target != null)
        {
            // Calculate the direction vector from this object to the target
            Vector3 directionToTarget = target.position - transform.position;

            // Calculate the rotation needed to look along that direction
            Quaternion targetRotation = Quaternion.LookRotation(directionToTarget);

            // Apply the rotation instantly
            transform.rotation = targetRotation;
        }
    }
}

Understanding the Direction Vector

The vector target.position - transform.position is crucial. It defines the vector from your object to the target. When Quaternion.LookRotation() is provided with this vector, it computes the target orientation where your object's forward axis aligns with this vector. This target orientation is the precise rotation your object should have to face the target.

Smooth Rotation with Quaternion.Slerp()

Instead of instantly snapping to the new rotation, you can smoothly interpolate towards it using Quaternion.Slerp(). This creates a much more natural and less jarring visual effect.

using UnityEngine;

public class SmoothLookAtTarget : MonoBehaviour
{
    public Transform target; // Assign your target object in the Inspector
    public float rotationSpeed = 5f; // Speed of rotation

    void Update()
    {
        if (target != null)
        {
            // Calculate the direction vector
            Vector3 directionToTarget = target.position - transform.position;

            // Calculate the desired rotation using LookRotation
            Quaternion targetRotation = Quaternion.LookRotation(directionToTarget);

            // Smoothly interpolate from current rotation to the target rotation
            transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
        }
    }
}
  • Pros:
    • Fine-grained control over orientation and up-direction.
    • Enables smooth rotation over time using interpolation.
    • Less prone to "flipping" issues compared to LookAt() when used carefully.
  • Cons:
    • Requires a bit more code to implement.

Practical Considerations

  • Up Vector: Both transform.LookAt() and Quaternion.LookRotation() have overloads that accept an up vector. This is useful if your object needs to maintain a specific "up" orientation while looking at the target (e.g., an airplane banking as it turns). By default, Vector3.up (world up) is used.

    // Example using an alternative up vector
    transform.LookAt(target.position, Vector3.forward); // Keeps object's forward aligned with world forward
    Quaternion targetRotation = Quaternion.LookRotation(directionToTarget, Vector3.up); // Ensure object's Y-axis points up
  • Locking Axes: If you only want an object to rotate on a single axis (e.g., a turret only rotating horizontally), you'll need to calculate the targetRotation and then constrain its axes before applying it.

    // Example: Only rotate on Y-axis (horizontal)
    Vector3 directionToTarget = target.position - transform.position;
    directionToTarget.y = 0; // Flatten the direction vector to ignore vertical difference
    
    if (directionToTarget != Vector3.zero) // Avoid LookRotation with zero vector
    {
        Quaternion targetRotation = Quaternion.LookRotation(directionToTarget);
        transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
    }
  • Target Offset: If you want your object to look at a specific point on the target, rather than its pivot, you can add an offset to target.position.

    Vector3 lookPoint = target.position + new Vector3(0, 1f, 0); // Look at 1 unit above target's pivot
    transform.LookAt(lookPoint);

Choosing the Right Method

Feature transform.LookAt() Quaternion.LookRotation() (with interpolation)
Ease of Use Very high (single line) Moderate (multiple lines for calculation and interpolation)
Instant Rotation Yes (by default) Can be instant or smooth (with Slerp/Lerp)
Control Basic (target and optional up vector) High (full control over forward and up vectors, allows axis locking)
Smoothness Abrupt (requires external smoothing) Inherently smooth when combined with Quaternion.Slerp()
Flipping Issues More prone in certain scenarios (e.g., target directly overhead) Less prone, especially with careful handling of the up vector and axis locking
Performance Lightweight Slightly more computation, but negligible in most cases

For simple, immediate "point-and-shoot" behaviors, transform.LookAt() is excellent. For dynamic cameras, enemy AI, character heads, or any situation demanding smooth, controlled orientation, Quaternion.LookRotation() combined with interpolation (Quaternion.Slerp()) provides the necessary power and flexibility.