Matrix4x4

One value that stores where something is, which way it faces and how big it is. You'll mostly meet it when drawing meshes from code or writing shaders.

A matrix is a recipe card for placing a toy: "make it twice as big, turn it to face right, then put it on the shelf." Follow the same card for every corner of the toy and the whole toy ends up in the right place.

Matrix4x4
TypeStruct (value type)
NamespaceUnityEngine

Do I need this?

Usually not. A Transform already handles position, rotation and scale for GameObjects. You need Matrix4x4 when there is no Transform, for example when you draw a mesh with Graphics.RenderMesh, or when you pass placement data to a shader.

You never have to fill in the 16 numbers yourself. Give Unity a position, rotation and scale and it builds the matrix.

Local vs world space

Local space = measured from the object itself. World space = measured from the centre of the scene. A cup's local position says where it sits on the table; its world position says where it is in the room. A matrix converts local into world.

The members you'll use

MemberWhat it does
Matrix4x4.TRS(pos, rot, scale)Builds a matrix from a position (T), rotation (R) and scale (S). Start here.
Matrix4x4.identityA matrix that changes nothing. Use this, not new Matrix4x4(), which is all zeros.
MultiplyPoint3x4(point)Moves, turns and scales a position.
MultiplyVector(dir)Turns and scales a direction but doesn't move it. A direction has no location, so moving it makes no sense.
inverseThe reverse recipe: world back to local.
transform.localToWorldMatrixThe matrix of an existing GameObject, including all its parents.

Example

Attach to any object and check the Console.

using UnityEngine;

public class MatrixExample : MonoBehaviour
{
    void Start()
    {
        // Move 10 right, turn 90° to the right, double the size
        Matrix4x4 m = Matrix4x4.TRS(new Vector3(10, 0, 0),
                                    Quaternion.Euler(0, 90, 0),
                                    Vector3.one * 2);

        Vector3 point = m.MultiplyPoint3x4(Vector3.forward); // (12, 0, 0)
        Vector3 dir   = m.MultiplyVector(Vector3.forward);    // (2, 0, 0): not moved by 10
        Debug.Log($"point {point}, direction {dir}");

        Vector3 back = m.inverse.MultiplyPoint3x4(point);     // about (0, 0, 1) again
        Debug.Log(back);
    }
}

The point (0,0,1) was scaled to (0,0,2), turned to (2,0,0), then moved to (12,0,0). The direction got the same scale and turn, but no move.

Combining matrices: order matters

You can combine two matrices with *. Read it right to left: in parent * child, the child's recipe happens first, then the parent's. Swapping them gives a different answer, just like "turn then walk" ends somewhere different from "walk then turn".

Matrix4x4 parent = Matrix4x4.TRS(new Vector3(5, 0, 0), Quaternion.Euler(0, 90, 0), Vector3.one);
Matrix4x4 child  = Matrix4x4.Translate(new Vector3(0, 0, 2));  // 2 forward
Vector3 p = (parent * child).MultiplyPoint3x4(Vector3.zero);    // (7, 0, 0)
Local pointChild matrixParent matrixWorld point
The matrix closest to the point is applied first.

What happens at runtime

  1. Your code builds a matrix (or reads one from a Transform).
  2. When drawing, Unity sends the matrix to the GPU.
  3. The shader applies it to every vertex. The mesh data itself is never changed.

Going further

Common Mistakes

See also