UnityでMatrix4x4を理解する
行列は何のためにあり、TRSはどう効くのか
Unityで3Dを触っていると、Matrix4x4 や localToWorldMatrix といった“行列”の存在に必ず出会います。
Transformで普段何気なくやっている「移動・回転・拡縮」や「親子階層の合成」「カメラ投影」などの裏側は、すべて行列で処理されています。
本記事では、
- そもそも行列は何のために使われるのか
- Unity / CGの中でどんな場面で登場するのか
- TRSとは何で、行列の中でどう振る舞うのか
- Unityでの基本的な使い方と、挙動確認の実験
を順番に整理していきます。
1. 行列の一番コアな役割:「変換」をまとめて扱うため
行列が強いのは、何かを別の状態へ“変換”するときです。
3D/Unityでの例
-
点やベクトルを動かす
- 位置の移動(平行移動)
- 回転
- 拡大縮小
-
座標系そのものを切り替える
- ローカル座標 → ワールド座標
- ワールド座標 → カメラ座標
- カメラ座標 → 画面座標(投影)
Transformが当たり前にやっている「位置・回転・拡縮」と「座標系変換」を、
数学的に一発で表してまとめられる形式が “行列” です。
2. いつ使われる?(Unity/CG文脈)
A. オブジェクトの姿勢を決めるとき
transform.position / rotation / scale の裏側は行列で合成されています。
- 子オブジェクトが親の動きについていく
→ 親の行列 × 子の行列 によってワールド姿勢が決まる
Transform階層が自然に「合成」できるのは、行列の掛け算があるからです。
B. カメラで“見える世界”を作るとき
カメラはこういう行列を持っています:
- View行列:ワールド → カメラの視点へ変換
- Projection行列:3D → 2Dへ投影
Unityのレンダリングは毎フレーム、
モデル行列(オブジェクト)
× ビュー行列(カメラ)
× プロジェクション行列(投影)
をGPUで大量に回しています。
C. たくさんの頂点を超高速に処理するとき
メッシュの頂点を1個ずつ position/rotation/scale で処理するより、
行列1個にまとめて、頂点すべてに同じ掛け算をする方が圧倒的に速いです。
GPUは「行列 × ベクトル」の並列計算が超得意なので、
行列はレンダリングのパイプラインにぴったり噛み合います。
3. Unity以外の“行列が自然に出る場面”
行列は「変換」だけでなく、複数の数値の関係を整理したいときにも現れます。
A. 物理・シミュレーション
- 剛体の回転
- 慣性テンソル
- バネの連立方程式
→ 多変数の関係を一気に解く形式として行列が自然に出る
B. 画像処理
- 画像の回転・拡大縮小・歪み補正
- フィルタ(ぼかし、シャープなど)
→ ピクセルの集合を変換するので行列で書ける
C. 機械学習・統計
- ニューラルネットの重み
- 多次元データの変換(PCAなど)
→ 大量の数値の「関係」を一つの“箱”として扱う
4. なぜ行列を使うと便利なのか?
行列の“得”は次の3つに尽きます。
① 変換を合成できる
「回転→移動→拡大縮小」みたいな複数ステップを
行列の掛け算1回で合成して1個にできる
Transform階層やカメラ処理の根幹です。
② 同じ変換を大量の点に一括適用できる
頂点100万個でも
行列 × ベクトル(点)を並列で回すだけ
GPUフレンドリーで高速。
③ 「座標系を変える」問題を統一的に扱える
ローカル→ワールド、ワールド→カメラ、など
全部同じ形式(行列)で扱えるため、パイプライン化しやすい。
5. 今の段階の「行列=何?」の固定イメージ
まずはこれだけ持っておけばOKです。
行列は 「空間やデータの変換ルールを一つにまとめたもの」
それを 掛け算で合成し、点やデータに一括で適用するために使う。
Unityの Matrix4x4 はその“変換ルール”の典型例です。
TRSとは何か?
TRS は、3D変換で最も基本になる “3つの要素” の略です。
T = Translation(平行移動 / 位置)
R = Rotation(回転)
S = Scale(拡大縮小)
UnityのTransformが持つ
position / rotation / scale をそのまま行列にまとめたものが TRS行列です。
TRSを「変換ルール」として見ると
TRS行列はこういうルールを意味します。
- **S(拡縮)**する
- **R(回転)**する
- **T(移動)**する
この3つを 1つの行列に圧縮して、点に一発適用できるようにしたものです。
Unityではこうやって作ります。
Matrix4x4 m = Matrix4x4.TRS(position, rotation, scale);
Unityでの直感的な対応
Transformと完全に対応しています。
Transform tr = transform;
// TransformのTRSが詰まった行列
Matrix4x4 m = Matrix4x4.TRS(tr.position, tr.rotation, tr.localScale);
// ほぼ同じものがTransformから直接取れる
Matrix4x4 localToWorld = tr.localToWorldMatrix;
-
Matrix4x4.TRS(...)
→ 「この position/rotation/scale で変換してね」行列を生成 -
transform.localToWorldMatrix
→ Transformが実際に使ってるTRS合成結果
ちょっと大事な話:行列内での順序
UnityのTRS行列は内部的に
M = T × R × S
の形でまとまっています。
点 p を変換するときは
p' = M × p = (T × R × S) × p
行列は 右側に書いた変換が先に効くルールがあるので、
実際の適用順は
S → R → T
になります。
つまり、
- まずサイズを変えて
- 次に回して
- 最後に移動する
というTransformの直感と一致するように設計されています。
簡単な実験コード(TRSの効き方を確認)
using UnityEngine;
public class TRSExample : MonoBehaviour
{
void Start()
{
Vector3 pos = new Vector3(3, 0, 0); // T
Quaternion rot = Quaternion.Euler(0, 90, 0); // R
Vector3 scl = new Vector3(2, 2, 2); // S
Matrix4x4 m = Matrix4x4.TRS(pos, rot, scl);
Vector3 p = new Vector3(1, 0, 0);
Vector3 p2 = m.MultiplyPoint3x4(p);
Debug.Log("original: " + p);
Debug.Log("after TRS: " + p2);
}
}
期待される変化(頭の中の形)
- (1,0,0) を 2倍 → (2,0,0)
- それを Y軸90°回転 → (0,0,-2)
- それを +3移動 → (3,0,-2)
というように、S→R→T の順で効くことが観察できます。
UnityでMatrix4x4を使う基本
ここからは、実際にUnity上で「行列がどう振る舞うか」を最低限固めます。
(A) TRS行列を作る
using UnityEngine;
public class MatrixBasicTRS : MonoBehaviour
{
void Start()
{
Vector3 position = new Vector3(3f, 0f, 0f);
Quaternion rotation = Quaternion.Euler(0f, 45f, 0f);
Vector3 scale = new Vector3(2f, 2f, 2f);
Matrix4x4 m = Matrix4x4.TRS(position, rotation, scale);
Debug.Log("TRS Matrix:\n" + m);
}
}
(B) 行列で点と方向を変換する
- 点(位置)に使う:
MultiplyPoint3x4 - 方向ベクトルに使う:
MultiplyVector
using UnityEngine;
public class MatrixBasicTransformPoint : MonoBehaviour
{
void Start()
{
Matrix4x4 m = Matrix4x4.TRS(
new Vector3(3f, 0f, 0f),
Quaternion.Euler(0f, 45f, 0f),
new Vector3(2f, 2f, 2f)
);
Vector3 p = new Vector3(1f, 0f, 0f);
Vector3 pTransformed = m.MultiplyPoint3x4(p);
Debug.Log("original point: " + p);
Debug.Log("transformed point: " + pTransformed);
Vector3 v = new Vector3(1f, 0f, 0f);
Vector3 vTransformed = m.MultiplyVector(v);
Debug.Log("original vector: " + v);
Debug.Log("transformed vector: " + vTransformed);
}
}
観察ポイント
-
MultiplyPoint3x4は 平行移動も含めて変換する -
MultiplyVectorは 平行移動を無視して回転と拡縮だけ受ける
→ 点は w=1、方向は w=0 の違いがここに出ます。
ミニ実験:平行移動が点だけに効くことを確認
using UnityEngine;
public class MatrixExperimentTranslationOnly : MonoBehaviour
{
void Start()
{
Matrix4x4 t = Matrix4x4.Translate(new Vector3(10f, 0f, 0f));
Vector3 p = new Vector3(1f, 2f, 3f);
Vector3 v = new Vector3(1f, 2f, 3f);
Debug.Log("Point before: " + p);
Debug.Log("Point after : " + t.MultiplyPoint3x4(p));
Debug.Log("Vector before: " + v);
Debug.Log("Vector after : " + t.MultiplyVector(v));
}
}
期待される振る舞い
- 点は (x+10, y, z) になる
- ベクトルは変わらない
「方向」には“どこにあるか”は関係ない、という直感と一致します。
ミニ実験:行列の掛け算順序で結果が変わることを確認
using UnityEngine;
public class MatrixExperimentOrder : MonoBehaviour
{
void Start()
{
Matrix4x4 T = Matrix4x4.Translate(new Vector3(3f, 0f, 0f));
Matrix4x4 R = Matrix4x4.Rotate(Quaternion.Euler(0f, 90f, 0f));
Vector3 p = new Vector3(1f, 0f, 0f);
Vector3 p1 = (T * R).MultiplyPoint3x4(p);
Vector3 p2 = (R * T).MultiplyPoint3x4(p);
Debug.Log("(T * R) result: " + p1);
Debug.Log("(R * T) result: " + p2);
}
}
形骸化すると
-
T * Rは「先にR、後にT」が点に適用 -
R * Tは「先にT、後にR」が点に適用
つまり
行列を右に書いた変換が先に効き、左に書いた変換が後に効く
という一般ルールがここで体感できます。
TransformとMatrix4x4の対応
using UnityEngine;
public class MatrixFromTransform : MonoBehaviour
{
void Start()
{
Matrix4x4 localToWorld = transform.localToWorldMatrix;
Matrix4x4 worldToLocal = transform.worldToLocalMatrix;
Debug.Log("localToWorld:\n" + localToWorld);
Debug.Log("worldToLocal:\n" + worldToLocal);
Vector3 localPoint = new Vector3(1f, 0f, 0f);
Vector3 worldPoint = localToWorld.MultiplyPoint3x4(localPoint);
Debug.Log("local point : " + localPoint);
Debug.Log("world point : " + worldPoint);
Vector3 backToLocal = worldToLocal.MultiplyPoint3x4(worldPoint);
Debug.Log("back to local: " + backToLocal);
}
}
-
localToWorldMatrixは ローカル → ワールド変換ルール -
worldToLocalMatrixはその逆変換(ほぼ逆行列)
まとめ
本記事の要点は次の通りです。
- 行列は 「変換ルールを一つにまとめる仕組み」
- Unityでは移動・回転・拡縮や座標系変換を 行列として合成・適用している
- TRS = Translation / Rotation / Scale
- TRS行列は内部的に T×R×S だが、点への適用順は S→R→T
-
MultiplyPoint3x4とMultiplyVectorの違いで
「点は移動を受ける / 方向は受けない」が体感できる
Discussion