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.
| Type | Struct (value type) |
|---|---|
| Namespace | UnityEngine |
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
| Member | What it does |
|---|---|
Matrix4x4.TRS(pos, rot, scale) | Builds a matrix from a position (T), rotation (R) and scale (S). Start here. |
Matrix4x4.identity | A 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. |
inverse | The reverse recipe: world back to local. |
transform.localToWorldMatrix | The 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)
What happens at runtime
- Your code builds a matrix (or reads one from a Transform).
- When drawing, Unity sends the matrix to the GPU.
- The shader applies it to every vertex. The mesh data itself is never changed.
Going further
- Normals (arrows pointing out of a surface) need special care if the scale is uneven, like (1, 3, 1). Use
m.inverse.transpose.MultiplyVector(normal).normalized. - Camera projection matrices add perspective. For those, use
MultiplyPoint, notMultiplyPoint3x4.
Common Mistakes
- Using
new Matrix4x4()as "no change". It's all zeros and squashes everything to a point. UseMatrix4x4.identity. - Using
MultiplyPoint3x4on a velocity or direction. It gets moved as well. UseMultiplyVector. - Multiplying in the wrong order and getting an object that orbits instead of sitting still.
See also
This page is a simplified, AI-assisted interpretation. For the complete and authoritative reference, see the official documentation.