Quick Syntax
Unity Matrix4x4는 column-major로 저장되며, column vector를 곱하는 M * p 형태로 읽습니다. 따라서 M = T * R * S는 local point에 S, R, T 순서로 적용됩니다. 위치(point)에는 translation이 들어가고, 방향(vector)에는 들어가지 않으므로 변환 메서드를 구분합니다.
Matrix4x4 localToWorld = Matrix4x4.TRS(position, rotation, scale);
Vector3 worldPoint = localToWorld.MultiplyPoint3x4(localPoint); // 이동 포함
Vector3 worldDirection = localToWorld.MultiplyVector(localDirection); // 이동 제외, scale 포함
// 계층: sword local -> hand local -> character world
Matrix4x4 swordWorld = characterWorld * handLocal * swordLocal;| 값의 의미 | 사용할 변환 | translation·scale 처리 |
|---|---|---|
| 위치, 메시 정점 | MultiplyPoint 또는 MultiplyPoint3x4 | translation 포함, 후자는 affine matrix에서 빠름 |
| 방향, velocity, normal 후보 | MultiplyVector | translation 제외, scale 영향은 남음 |
| rotation·position·scale 조합 | Matrix4x4.TRS | Unity Transform과 같은 TRS 의도 표현 |
곱 순서와 적용 순서
행렬 곱은 교환 법칙이 성립하지 않습니다. T * R * S와 R * T * S는 같은 숫자를 포함해도 다른 공간 변환입니다. Unity의 M * p 표기에서는 오른쪽 행렬이 먼저 point에 적용됩니다. 그래서 T * R * S * localPoint는 local object를 먼저 scale하고, 회전한 뒤 world 위치로 옮깁니다.
M = T * R * S
worldPoint = M * localPoint
적용: localPoint -> scale -> rotate -> translate -> worldPoint이 설명은 Unity의 matrix/vector convention을 전제로 합니다. 다른 graphics API, shader code, 수학 라이브러리는 row vector를 쓰거나 행렬을 다른 순서로 표현할 수 있습니다. 코드 조각을 옮길 때는 행렬이 어느 공간에서 어느 공간으로 가는지와 point를 왼쪽·오른쪽 중 어디에 곱하는지를 같이 확인합니다.
계층과 point·direction 구분
자식의 world matrix는 자식 local matrix에 부모의 world matrix가 누적된 결과입니다. 검을 손 본에 붙이면 검 local offset이 먼저 손 공간으로 변하고, 그 다음 손·팔·캐릭터 world 변환이 적용됩니다. parentWorld * childLocal처럼 순서를 명시하면 local/world 값을 섞는 문제를 줄일 수 있습니다.
homogeneous coordinate에서는 point의 w가 1이고 direction의 w가 0입니다. 이 차이 때문에 MultiplyPoint3x4는 translation을 적용하지만 MultiplyVector는 translation을 무시합니다. 바람 방향이나 velocity를 point처럼 변환하면 오브젝트 위치만큼 방향이 틀어집니다. non-uniform scale이 있는 normal은 단순 MultiplyVector로 올바르게 변환되지 않을 수 있으므로 renderer·shader의 normal matrix 처리와 분리합니다.
음수 scale과 디버깅
음수 scale은 미러링에 쓸 수 있지만 determinant 부호를 바꿔 winding, face culling, normal, collider, child Transform에 영향을 줄 수 있습니다. 항상 피할 값은 아니며, mesh·shader·physics·animation에서 어떤 결과가 나오는지 해당 asset과 pipeline에서 확인해야 합니다. “rotation으로 대체”가 같은 시각 결과를 보장하는 것도 아닙니다.
행렬 결과가 이상하면 행렬 원소부터 고치기 전에 local -> world, world -> view처럼 각 값의 공간을 쓰고, point인지 direction인지, parent 누적 순서가 맞는지 확인합니다. 일반 gameplay script에서는 Transform과 Vector3·Quaternion API가 행렬 직접 계산보다 오류를 줄이는 경우가 많고, custom projection·mesh deformation·graphics API 연결처럼 행렬이 실제 요구일 때만 Matrix4x4를 직접 다룹니다.
T * R * S는 문자열 순서가 아니라 Unity의 M * p convention에서 오른쪽부터 적용되는 변환입니다. point와 direction, local과 world를 구분하지 않으면 행렬값이 맞아도 위치·방향이 함께 틀어집니다.
참고 링크
2 sources