Unity3D數學第三篇:坐標系與變換矩陣(空間轉換篇)

Unity3D數學第一篇:向量與點、線、面(基礎篇)

Unity3D數學第二篇:旋轉與歐拉角、四元數(核心變換篇)

Unity3D數學第三篇:坐標系與變換矩陣(空間轉換篇)

Unity3D數學第四篇:射線與碰撞檢測(交互基礎篇)

Unity3D數學第五篇:幾何計算與常用算法(實用算法篇)

第三篇:坐標系與變換矩陣(空間轉換篇)

在 3D 游戲開發中,我們不斷地在不同的“參考系”或“視角”之間切換。一個物體的“前方”可能相對于它自身,也可能相對于整個世界;鼠標點擊的屏幕位置,最終要對應到 3D 世界中的某個點。這些轉換的背后,離不開坐標系 (Coordinate Systems)變換矩陣 (Transformation Matrices) 的強大作用。

本篇教程將深入探討 Unity 中各種常見的坐標系,揭示它們之間的轉換機制,并為你揭開變換矩陣這一“幕后英雄”的面紗。理解這些概念,將讓你對 3D 空間中的一切變換擁有更深刻的洞察力。


1. 深入理解坐標系:3D 空間的“視角”

想象一個房間,你可以在房間的中心描述一件家具的位置(例如,“它在我前面兩米”),也可以相對于房間的墻角來描述(例如,“它在東墻角往北三米,往西兩米”)。這兩種描述方式,分別對應著不同的坐標系。

在 3D 游戲世界中,存在多種相互關聯的坐標系,它們服務于不同的目的。

1.1 局部坐標系 (Local Space / Object Space)

  • 概念: 每個獨立的 3D 物體都有其自身的局部坐標系。這個坐標系的原點通常位于物體的中心點(或稱為軸心點 Pivot),而它的 X、Y、Z 軸則沿著物體自身的特定方向。

    • 例如,一個汽車模型,它的局部 Y 軸通常指向它的“上方”(車頂),局部 Z 軸指向它的“前方”(車頭),局部 X 軸指向它的“右方”。
  • 特性: 當物體自身旋轉或移動時,它的局部坐標系也跟著它一起旋轉和移動。因此,一個點在物體局部坐標系中的坐標是固定不變的

  • Unity 中的體現:

    • Transform.localPosition:表示物體相對于其父對象的局部位置。如果物體沒有父對象,則等同于 transform.position

    • Transform.localRotation:表示物體相對于其父對象的局部旋轉。

    • Transform.localScale:表示物體相對于其父對象的局部縮放。

    • transform.forwardtransform.uptransform.right:這些便捷屬性返回的是物體在世界坐標系下其局部 Z、Y、X 軸的方向向量。例如,transform.forward 就是物體當前面向的世界方向

1.2 世界坐標系 (World Space)

  • 概念: 整個 3D 場景的全局、固定參考系。它的原點通常位于 (0, 0, 0),X、Y、Z 軸指向固定方向。在 Unity 中,通常:

    • X 軸: 指向右方 (Red Axis)

    • Y 軸: 指向上方 (Green Axis)

    • Z 軸: 指向前方 (Blue Axis)

  • 特性: 世界坐標系是所有物體共享的“大地圖”。所有物體最終都會被放置在世界坐標系中的某個位置和姿態。

  • Unity 中的體現:

    • Transform.position:表示物體在世界坐標系中的位置。

    • Transform.rotation:表示物體在世界坐標系中的旋轉。

    • Transform.lossyScale:表示物體在世界坐標系中的最終縮放(包含了父級的縮放影響)。

1.3 父子關系與層級變換

在 Unity 中,游戲對象可以有父子關系。當一個對象成為另一個對象的子對象時,它的局部坐標系就變成了相對于其父對象的坐標系。子對象的任何變換都會受到父對象變換的影響。

  • 示例: 如果一個手臂是身體的子對象,當身體旋轉時,手臂也會跟著旋轉(因為手臂的局部坐標系隨著身體的世界坐標系一起旋轉了)。而手臂自身的局部旋轉,則是相對于它當前所處的“父級空間”進行的。

  • Transform.SetParent() 方法可以用來建立和解除父子關系,這在運行時動態組合對象時非常有用,例如拾取武器或附件。


為什么要區分局部坐標系和世界坐標系?

理解這些坐標系的關鍵在于它們處理問題的方式:

  • 局部坐標系方便描述物體自身的屬性(例如,我向前走,就是沿著我的局部 Z 軸),因為它不受外部環境變化的影響。

  • 世界坐標系方便描述物體在整個場景中的絕對位置和關系(例如,哪個物體離世界原點最近),因為它是一個統一的參考標準。

在游戲開發中,我們經常需要在兩者之間進行轉換。

1.4 屏幕坐標系 (Screen Space)

  • 概念: 你的游戲屏幕(或窗口)上的 2D 像素坐標系。

    • 原點通常在屏幕的左下角 (0, 0)

    • X 軸向右延伸,Y 軸向上延伸。

    • Z 軸通常表示深度,即點離攝像機的距離。

  • 特性: 像素單位,直接對應屏幕上的視覺呈現。

  • Unity 中的體現:

    • Input.mousePosition:鼠標在屏幕上的像素坐標。

    • Input.GetTouch(0).position:觸控點在屏幕上的像素坐標。

    • UI Canvas 的 Screen Space - Overlay 模式下的 UI 元素位置。

1.5 視口坐標系 (Viewport Space)

  • 概念: 相機在渲染時看到的**“視口”**的 2D 歸一化坐標系。

    • 原點在視口的左下角 (0, 0)

    • 右上角是 (1, 1)

    • X、Y 值范圍是 0.01.0

    • Z 軸同樣表示深度,即點離攝像機的距離。

  • 特性: 獨立于屏幕分辨率。無論屏幕多大,視口左下角始終是 (0,0),右上角始終是 (1,1)。這對于判斷物體是否在屏幕內非常有用。

  • Unity 中的體現:

    • Camera.WorldToViewportPoint():世界坐標轉視口坐標。

    • Camera.ViewportToWorldPoint():視口坐標轉世界坐標。

    • Camera.ViewportToScreenPoint():視口坐標轉屏幕坐標。

1.6 其他重要但無需深究的坐標系

  • 攝像機空間 (Camera Space / View Space): 以攝像機自身為原點和軸向的 3D 坐標系。所有物體在渲染前都會被轉換到這個空間。

  • 裁剪空間 (Clip Space): 在攝像機空間之后,點被投影到一個立方體(歸一化設備坐標,NDC)中。這個空間用于剔除視錐體外的點。

  • 歸一化設備坐標 (Normalized Device Coordinates - NDC): 經過裁剪空間后,所有可見點被映射到一個標準的立方體中,X, Y, Z 軸范圍都是 [-1, 1]

這些更深層次的坐標系主要在圖形渲染管線內部使用,作為開發者,通常只需要理解它們的存在和作用流程,而無需手動操作它們。了解它們能讓你更好地理解 3D 世界最終如何映射到 2D 屏幕上。


2. 坐標系轉換:在不同“視角”之間穿梭

在游戲開發中,我們經常需要在不同坐標系之間進行點的轉換,例如將一個世界坐標的點轉換為局部坐標,或者將鼠標的屏幕坐標轉換為 3D 世界中的點擊點。Unity 提供了方便的 API 來實現這些轉換。

2.1 局部坐標系與世界坐標系之間的轉換

這些方法都可以在任何 Transform 組件上調用。

  • Transform.TransformPoint(Vector3 position):局部點轉世界點

    • 將一個在當前 Transform局部坐標系中定義的點 (position) 轉換到世界坐標系中。

    • 應用: 計算角色前方 N 米處的世界坐標、計算子彈從槍口(作為局部點)射出的世界起始位置。

    C#

    // Unity
    // 假設你在物體 A 上,想知道物體 A 的局部坐標 (0, 0, 5) 在世界中的位置
    Vector3 localPoint = new Vector3(0, 0, 5); // 物體 A 前方 5 米處
    Vector3 worldPoint = transform.TransformPoint(localPoint);
    Debug.Log($"局部點 {localPoint} 在世界中是 {worldPoint}");
  • Transform.InverseTransformPoint(Vector3 position):世界點轉局部點

    • 將一個在世界坐標系中定義的點 (position) 轉換到當前 Transform局部坐標系中。

    • 應用: 判斷一個世界中的點相對于物體的具體方位(例如,敵人相對于我在哪里)、計算局部碰撞點。

    C#

    // Unity
    // 假設你想知道世界坐標 (10, 0, 0) 相對于當前物體的位置
    Vector3 worldPoint = new Vector3(10, 0, 0);
    Vector3 localPoint = transform.InverseTransformPoint(worldPoint);
    Debug.Log($"世界點 {worldPoint} 相對于我是在 {localPoint}");
  • Transform.TransformDirection(Vector3 direction):局部方向轉世界方向

    • 將一個在當前 Transform局部坐標系中定義的方向向量 (direction) 轉換到世界坐標系中。

    • 重要: 這個方法只處理旋轉,不考慮平移和縮放。它將局部方向向量的方向轉換到世界空間,但不會改變其長度。

    • 應用: 獲取物體當前的世界前方 (transform.TransformDirection(Vector3.forward) 等同于 transform.forward),獲取物體自身某個方向在世界中的表示。

    C#

    // Unity
    // 獲取當前物體局部右方在世界中的方向
    Vector3 localRight = Vector3.right;
    Vector3 worldRight = transform.TransformDirection(localRight);
    Debug.Log($"我的局部右方在世界中是 {worldRight}");
  • Transform.InverseTransformDirection(Vector3 direction):世界方向轉局部方向

    • 將一個在世界坐標系中定義的向量 (direction) 轉換到當前 Transform局部坐標系中。

    • 同樣,只處理旋轉,不考慮平移和縮放

    • 應用: 判斷世界中的某個力或方向向量對于物體自身來說是哪個方向(例如,世界重力對于斜坡上的角色來說是哪個局部方向)。

    C#

    // Unity
    // 假設你想知道世界坐標的 Vector3.up (世界向上) 對于當前物體是哪個局部方向
    Vector3 worldUp = Vector3.up;
    Vector3 localUp = transform.InverseTransformDirection(worldUp);
    Debug.Log($"世界向上對于我來說是局部 {localUp}");
  • Transform.TransformVector(Vector3 vector)Transform.InverseTransformVector(Vector3 vector)

    • 這兩個方法與 TransformDirection 類似,但它們會考慮縮放。當處理法線(需要逆轉置矩陣)或非單位長度的向量時,需要特別注意。在大多數情況下,處理方向用 TransformDirection 即可,除非你明確需要考慮縮放對向量的影響。

2.2 世界坐標系與屏幕/視口坐標系之間的轉換

這些方法通常在 Camera 組件上調用。

  • Camera.WorldToScreenPoint(Vector3 position):世界點轉屏幕點

    • 將 3D 世界坐標系中的一個點 (position) 轉換到 2D 屏幕坐標系中。返回的 Vector3xy 是像素坐標,z 是該點距離攝像機的深度。

    • 應用:

      • 將 3D 物體在屏幕上方的位置顯示一個血條 UI。

      • 判斷一個 3D 物體是否在屏幕內(檢查 x, y 是否在 0Screen.width/Screen.height 之間,且 z > 0)。

    C#

    // Unity
    public Transform target3DObject;
    void Update() {Vector3 screenPos = Camera.main.WorldToScreenPoint(target3DObject.position);Debug.Log($"3D 物體 {target3DObject.name} 在屏幕上的位置是 {screenPos}");// 判斷是否在屏幕內:if (screenPos.z > 0 && screenPos.x >= 0 && screenPos.x <= Screen.width && screenPos.y >= 0 && screenPos.y <= Screen.height) {Debug.Log("物體在屏幕內!");} else {Debug.Log("物體在屏幕外!");}
    }
  • Camera.ScreenToWorldPoint(Vector3 position):屏幕點轉世界點

    • 將 2D 屏幕坐標系中的一個點 (position) 轉換到 3D 世界坐標系中。

    • 關鍵: 由于 2D 屏幕點缺少深度信息,你必須手動為 position.z 賦值,才能確定它在 3D 空間中的深度。

    • 應用:

      • 點擊屏幕獲取 3D 世界中的一個點(例如,點擊地面進行移動)。

      • 將 UI 元素的位置映射到 3D 空間中的特定深度。

    C#

    // Unity
    // 鼠標點擊屏幕,獲取點擊處在世界中的位置
    void Update() {if (Input.GetMouseButtonDown(0)) {Vector3 mouseScreenPos = Input.mousePosition;// 必須提供 Z 深度信息!這里假設我們想在相機前方 10 米處獲取世界點mouseScreenPos.z = 10f; // 這里的 z 是指離相機近裁剪面的距離Vector3 worldClickPoint = Camera.main.ScreenToWorldPoint(mouseScreenPos);Debug.Log($"鼠標點擊屏幕 {Input.mousePosition} 對應世界點 {worldClickPoint}");}
    }

    注意: 如果你需要精確點擊 3D 物體表面,通常會結合射線檢測 (Raycasting) 來獲取深度,這比固定 z 值更精確。我們會在第四篇詳細講解。

  • Camera.WorldToViewportPoint(Vector3 position):世界點轉視口點

    • 將 3D 世界坐標系中的一個點 (position) 轉換到 2D 視口坐標系中。返回的 Vector3xy 范圍是 0.01.0z 是深度。

    • 應用:

      • 判斷物體是否在屏幕內(通常比 WorldToScreenPoint 更方便,因為它不依賴 Screen.width/height)。

      • 創建位于屏幕相對位置的 UI 元素(例如,血條總在敵人上方,但不能超出屏幕)。

    C#

    // Unity
    public Transform targetObject;
    void Update() {Vector3 viewportPos = Camera.main.WorldToViewportPoint(targetObject.position);if (viewportPos.z > 0 && viewportPos.x >= 0 && viewportPos.x <= 1 && viewportPos.y >= 0 && viewportPos.y <= 1) {Debug.Log("物體在視口內!");} else {Debug.Log("物體在視口外!");}
    }
  • Camera.ViewportToWorldPoint(Vector3 position):視口點轉世界點

    • 將 2D 視口坐標系中的一個點 (position) 轉換到 3D 世界坐標系中。

    • 同樣需要手動提供 position.z 深度。

    • 應用: 將一個位于屏幕中央(0.5, 0.5)的 UI 元素映射到 3D 世界中的某個深度。


3. 變換矩陣:空間轉換的幕后英雄

在所有的坐標系轉換背后,真正執行“數學魔法”的是變換矩陣 (Transformation Matrices)。雖然 Unity 為我們封裝了大多數底層矩陣操作,但理解它們的存在和作用原理,能讓你更深刻地理解 3D 圖形學,并在遇到復雜問題時游刃有余。

3.1 什么是變換矩陣?

  • 概念: 在 3D 圖形中,一個矩陣 (Matrix) 是一個矩形排列的數字集合。一個 4x4 的矩陣可以同時表示 3D 空間中的平移 (Translation)旋轉 (Rotation)縮放 (Scaling) 這三種基本變換。

  • 矩陣乘法: 當一個 3D 點(表示為齊次坐標下的向量)與一個變換矩陣相乘時,就可以得到變換后的新點。

    • 例如,NewPoint = Matrix * OldPoint
  • 關鍵特性:不滿足交換律! MatrixA * MatrixB 不等于 MatrixB * MatrixA。這意味著變換的順序至關重要。先旋轉再平移,和先平移再旋轉,會得到完全不同的結果。這解釋了為什么 Unity 中 Transform 組件的 positionrotation 操作是分開的,以及為什么父子變換的順序會影響最終結果。

3.2 矩陣如何工作?(簡要原理)

一個 4x4 的變換矩陣通常結構如下:

| Sx  0   0   Tx |
| 0   Sy  0   Ty |
| 0   0   Sz  Tz |
| 0   0   0   1  |
  • 其中 Sx, Sy, Sz 控制縮放

  • 矩陣左上角的 3x3 部分(包含 0 和對角線上的值)控制旋轉

  • Tx, Ty, Tz 控制平移

當一個 3D 點 (x, y, z, 1)(這里的 1 是齊次坐標的約定)與這個矩陣相乘時,就能同時實現平移、旋轉和縮放。

3.3 MVP 矩陣:3D 世界到 2D 屏幕的渲染管線

在 3D 渲染管線中,一個 3D 模型從其自身定義到最終呈現在屏幕上,會經歷一系列的坐標系轉換,這些轉換都由特定的變換矩陣完成。這就是著名的 MVP 矩陣

  1. 模型矩陣 (Model Matrix / World Matrix):局部空間 -> 世界空間

    • 作用: 將 3D 模型在它自己的局部坐標系中定義的頂點,轉換到世界坐標系中。

    • 每個物體都有一個模型矩陣,它由該物體的 Transform.positionTransform.rotationTransform.localScale 決定。

    • 例如,一個角色模型,它的模型矩陣決定了它在世界中的位置、方向和大小

  2. 視圖矩陣 (View Matrix):世界空間 -> 攝像機空間

    • 作用:世界坐標系中的所有點,轉換到攝像機(或觀察者)的局部坐標系中。這相當于從攝像機的角度“看”世界。

    • 視圖矩陣實際上是攝像機自身變換矩陣的逆矩陣

    • 它模擬了攝像機的位置和朝向

  3. 投影矩陣 (Projection Matrix):攝像機空間 -> 裁剪空間/NDC 空間

    • 作用:攝像機空間中的 3D 點,投影到 2D 屏幕上,并進行深度擠壓和透視變換

    • 它定義了攝像機的視野 (Field of View - FOV)近裁剪面 (Near Clip Plane)遠裁剪面 (Far Clip Plane)

    • 兩種主要類型:

      • 透視投影 (Perspective Projection): 模擬人眼看世界的效果,遠的物體小,近的物體大,有透視感。

      • 正交投影 (Orthographic Projection): 沒有透視感,所有物體大小不變,常用于 2D 游戲、工程視圖或特殊的 3D 效果。

    • 投影矩陣的輸出通常是裁剪空間,然后通過除以 W 分量(透視除法)進入歸一化設備坐標 (NDC) 空間,X、Y、Z 軸范圍都是 [-1, 1]

渲染管線中的流程:

頂點數據 (局部坐標) -> 模型矩陣 -> 世界坐標 -> 視圖矩陣 -> 攝像機空間 -> 投影矩陣 -> 裁剪空間 -> 透視除法 -> NDC 空間 -> 視口變換 -> 屏幕坐標 -> 最終渲染


為什么要理解 MVP 矩陣?

雖然 Unity 幫你處理了所有這些復雜的矩陣乘法,但了解 MVP 矩陣的工作原理,能讓你:

  • 理解 3D 渲染的底層邏輯: 當你在 Shader 中處理頂點或像素時,你是在哪個坐標系下操作?這直接影響你的計算結果。

  • 調試渲染問題: 當物體顯示不正確時,可能是哪個矩陣出了問題?

  • 實現自定義渲染效果: 如果你需要編寫自定義的渲染管道或著色器,對 MVP 矩陣的理解是必不可少的。


4. 坐標系與變換矩陣在 Unity 中的高級應用

理解坐標系和矩陣的工作方式后,我們可以解決一些實際的游戲開發問題。

4.1 鼠標點擊精確拾取 3D 物體(結合射線)

這是最常見的應用之一。鼠標點擊的 2D 屏幕點,如何找到它在 3D 世界中擊中的物體?

C#

// Unity
void Update() {if (Input.GetMouseButtonDown(0)) {// 1. 將鼠標的屏幕坐標轉換為一條射線// Camera.main.ScreenPointToRay() 會根據相機位置和方向,從屏幕點發射一條射線Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);// 2. 聲明一個 RaycastHit 結構體來存儲射線檢測結果RaycastHit hit;// 3. 執行射線檢測// Physics.Raycast 會沿著射線方向檢測碰撞體if (Physics.Raycast(ray, out hit, 100f)) { // 100f 是射線的最大檢測距離Debug.Log($"鼠標點擊了物體: {hit.collider.gameObject.name},在世界坐標: {hit.point}");// 你可以對 hit.collider.gameObject 進行操作,例如選中、高亮} else {Debug.Log("沒有點擊到任何 3D 物體。");}}
}

這里的核心就是將 2D 的屏幕坐標,通過攝像機的投影信息反推回 3D 世界中的一條射線

4.2 UI 元素跟隨 3D 物體(血條、名稱板)

讓一個 UI 元素(例如角色的血條或名稱板)始終位于其對應的 3D 角色上方。

C#

// Unity
public Transform target3DCharacter; // 要跟隨的 3D 角色
public RectTransform uiElementRectTransform; // 要跟隨的 UI 元素的 RectTransformvoid Update() {if (target3DCharacter == null || uiElementRectTransform == null || Camera.main == null) return;// 1. 將 3D 角色頭頂的世界坐標轉換為屏幕坐標// 假設血條在角色頭頂上方 2 個單位處Vector3 worldPositionAboveCharacter = target3DCharacter.position + Vector3.up * 2f;Vector3 screenPosition = Camera.main.WorldToScreenPoint(worldPositionAboveCharacter);// 2. 判斷物體是否在攝像機前方且在屏幕內(防止血條顯示在屏幕外或背后)if (screenPosition.z > 0 &&screenPosition.x >= 0 && screenPosition.x <= Screen.width &&screenPosition.y >= 0 && screenPosition.y <= Screen.height) {uiElementRectTransform.gameObject.SetActive(true); // 顯示 UI 元素// 3. 將屏幕坐標轉換為 UI Canvas 的 RectTransform 坐標// UI 坐標通常是相對于 Canvas 的,需要特殊處理Vector2 localUIPos;RectTransformUtility.ScreenPointToLocalPointInRectangle(uiElementRectTransform.parent as RectTransform, // UI 元素的父級 Canvas RectTransformscreenPosition,Camera.main.WorldToScreenPoint(Camera.main.transform.position).z, // 假設 Z 深度相同out localUIPos);// 如果 Canvas 是 Screen Space - Camera 模式,第三個參數是 Camera.main// 如果 Canvas 是 Screen Space - Overlay 模式,第三個參數是 null// 鑒于目前是 Screen Space - Overlay,直接使用 screenPosition 即可// 或者更簡單的,直接賦值,Unity UI 系統會處理好:uiElementRectTransform.position = screenPosition;} else {uiElementRectTransform.gameObject.SetActive(false); // 隱藏 UI 元素}
}

注意: 對于 Unity UI,RectTransformUtility.ScreenPointToLocalPointInRectangle 通常用于將屏幕點轉換為 Canvas 內部的局部坐標,這取決于你的 Canvas 渲染模式(Screen Space - OverlayScreen Space - CameraWorld Space)。這里為了簡化,如果 Canvas 是 Screen Space - Overlay 模式,直接將 uiElementRectTransform.position = screenPosition; 即可,Unity 會處理其與屏幕坐標的映射。

4.3 相機邊界限制

限制相機只能在特定區域內移動,或者當玩家靠近屏幕邊緣時,相機自動平移。

C#

// Unity
public Transform player;
public float edgeOffset = 0.1f; // 屏幕邊緣觸發區域 (0-1 范圍)
public float cameraMoveSpeed = 5f;void Update() {// 1. 將玩家位置轉換為視口坐標Vector3 viewportPos = Camera.main.WorldToViewportPoint(player.position);Vector3 cameraMoveDirection = Vector3.zero;// 2. 檢查玩家是否接近視口邊緣if (viewportPos.x < edgeOffset) {cameraMoveDirection += Vector3.left;} else if (viewportPos.x > 1f - edgeOffset) {cameraMoveDirection += Vector3.right;}if (viewportPos.y < edgeOffset) {cameraMoveDirection += Vector3.down;} else if (viewportPos.y > 1f - edgeOffset) {cameraMoveDirection += Vector3.up;}// 3. 移動相機Camera.main.transform.position += cameraMoveDirection.normalized * cameraMoveSpeed * Time.deltaTime;
}

這里利用視口坐標系的歸一化特性,方便地判斷玩家相對于屏幕邊緣的位置。


5. 常見面試題與深入思考

5.1 面試問答

  1. 問:請解釋局部坐標系和世界坐標系的區別。在 Unity 中,當物體存在父子關系時,transform.positiontransform.localPosition 有何不同?

    • 解析:

      • 局部坐標系: 物體自身的坐標系,原點在物體軸心,軸向與物體自身方向一致。描述物體自身的幾何數據。

      • 世界坐標系: 整個場景的全局、固定坐標系,原點在 (0,0,0),軸向固定。描述物體在整個世界中的絕對位置。

      • transform.position 表示物體在世界坐標系中的絕對位置。

      • transform.localPosition 表示物體在父對象局部坐標系中的相對位置。如果物體沒有父對象,則 localPosition 等同于 position。當父對象移動或旋轉時,子對象的 localPosition 不變,但其 position 會隨父對象而改變。

  2. 問:如何在 Unity 中將一個世界坐標的點轉換到某個物體的局部坐標系?請舉例說明應用場景。

    • 考察點: InverseTransformPoint 的使用及其應用。

    • 解析: 使用 transform.InverseTransformPoint(worldPoint) 方法。

      • 應用場景:

        • 判斷一個世界中的目標點相對于當前物體的方位。例如,一個 AI 想要知道玩家在它自身的左側還是右側、前方還是后方,就需要將玩家的世界位置轉換為 AI 的局部坐標,然后判斷 X、Z 分量的正負。

        • 獲取一個物體被擊中時,局部碰撞點在哪里,這在制作特效(例如粒子效果從特定部位發出)或計算局部傷害時很有用。

  3. 問:請簡要描述 MVP 矩陣在 3D 渲染管線中的作用。它們分別負責什么轉換?

    • 考察點: 對 3D 圖形渲染基礎流程的理解,矩陣的抽象作用。

    • 解析:

      • MVP 矩陣是 3D 世界中的點最終如何被渲染到 2D 屏幕上的關鍵。

      • 模型矩陣 (Model Matrix): 將模型自身的局部坐標轉換為世界坐標。它決定了物體在世界中的位置、旋轉和縮放

      • 視圖矩陣 (View Matrix):世界坐標轉換為攝像機(觀察者)的局部坐標。它模擬了攝像機的位置和朝向

      • 投影矩陣 (Projection Matrix):攝像機空間中的 3D 點投影到 2D 屏幕(歸一化設備坐標),并進行透視變換和裁剪。它定義了攝像機的視野 (FOV)、近遠裁剪面,決定了最終畫面的透視感或正交感。

    • 總結: 模型矩陣定位物體;視圖矩陣選擇觀察視角;投影矩陣定義如何將 3D 世界映射到 2D 屏幕。

  4. 問:如何在 Unity 中讓一個 UI 元素(例如血條)始終跟隨一個 3D 角色顯示在它的頭頂?你會用到哪些坐標系轉換?

    • 考察點: 綜合運用 WorldToScreenPoint 和 UI 坐標系轉換的理解。

    • 解析:

      1. 首先,獲取 3D 角色頭頂的世界坐標

      2. 使用 Camera.main.WorldToScreenPoint() 將這個世界坐標轉換為屏幕坐標(像素坐標)。

      3. 然后,將這個屏幕坐標賦值給 UI 元素的 RectTransform.position

      4. 額外考慮: 需要判斷 WorldToScreenPoint 返回的 z 值是否大于 0(在攝像機前方),以及 x, y 是否在屏幕范圍內,以決定是否顯示 UI 元素,避免顯示在屏幕外或角色背后。對于不同 Canvas 渲染模式下的 UI 定位,可能還需要額外的 RectTransformUtility 轉換。


總結與展望

本篇教程深入探討了 3D 游戲開發中至關重要的坐標系變換矩陣

  • 我們詳細區分了局部坐標系、世界坐標系、屏幕坐標系和視口坐標系,理解了它們各自的用途。

  • 掌握了 Unity 中局部與世界世界與屏幕/視口之間進行轉換的各種 API,讓你能夠靈活處理位置和方向的轉換。

  • 揭示了變換矩陣的底層原理,包括其表示平移、旋轉、縮放的能力,以及不滿足交換律的重要性。

  • 深入理解了 MVP 矩陣 (模型、視圖、投影矩陣) 在 3D 渲染管線中的核心作用,讓你對 3D 畫面如何呈現在屏幕上有了更清晰的認識。

對坐標系和變換的理解,是你在 Unity 中構建復雜層級結構、實現相機邏輯、處理 UI 交互以及深入圖形渲染的基石。

在下一篇《射線與碰撞檢測(交互基礎篇)》中,我們將結合你已經掌握的向量、旋轉、坐標系知識,深入學習如何在 3D 世界中進行精確的交互檢測,例如鼠標點擊拾取、子彈命中判斷以及各種物理碰撞。

現在,你對坐標系和變換矩陣的概念是否已經更加清晰了呢?在 Unity 開發中,你是否曾遇到過因坐標系混淆而導致的問題?

Unity3D數學第一篇:向量與點、線、面(基礎篇)

Unity3D數學第二篇:旋轉與歐拉角、四元數(核心變換篇)

Unity3D數學第三篇:坐標系與變換矩陣(空間轉換篇)

Unity3D數學第四篇:射線與碰撞檢測(交互基礎篇)

Unity3D數學第五篇:幾何計算與常用算法(實用算法篇)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/93930.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/93930.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/93930.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

UV安裝并設置國內源

文章目錄一、UV下載1.官方一鍵安裝2.github下載安裝二、更換國內鏡像源&#xff08;加速下載&#xff09;方法1&#xff1a;臨時環境變量&#xff08;單次生效&#xff09;方法2&#xff1a;永久配置&#xff08;推薦&#xff09;方法3&#xff1a;命令行直接指定源三、驗證鏡像…

1 前言:什么是 CICD 為什么要學 CICD

什么是 CI/CD 我的資源庫網站&#xff1a;https://www.byteooo.cn 在開發階段&#xff0c;許多編譯工具會將我們的源碼編譯可使用的文件。例如 vue-cli 的項目會被 webpack 打包編譯為瀏覽器的文件&#xff0c;Java 項目會被編譯為 .class/jar 文件以供服務器使用。 但是&am…

GitHub 趨勢日報 (2025年07月30日)

&#x1f4ca; 由 TrendForge 系統生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日報中的項目描述已自動翻譯為中文 &#x1f4c8; 今日獲星趨勢圖 今日獲星趨勢圖3579copyparty752supervision664500-AI-Agents-Projects483awesome403prompt-optim…

“非參數化”大語言模型與RAG的關系?

這個問題觸及了一個關鍵的技術細節&#xff0c;兩者關系密切&#xff0c;但層面不同&#xff1a; “非參數化”大語言模型是一個更廣泛的概念或類別&#xff0c;而RAG&#xff08;Retrieval-Augmented Generation&#xff09;是實現這一概念最主流、最具體的一種技術框架。 您可…

LeetCode Hot 100:15. 三數之和

題目給你一個整數數組 nums &#xff0c;判斷是否存在三元組 [nums[i], nums[j], nums[k]] 滿足 i ! j、i ! k 且 j ! k &#xff0c;同時還滿足 nums[i] nums[j] nums[k] 0 。請你返回所有和為 0 且不重復的三元組。注意&#xff1a;答案中不可以包含重復的三元組。示例 1&…

銀行回單識別應用場景剖析

銀行回單OCR識別技術通過自動化處理紙質或電子回單中的關鍵信息&#xff0c;顯著提升了金融、企業及個人場景下的數據管理效率。以下是其核心應用場景及價值的詳細剖析&#xff1a;一、企業財務場景自動化賬務處理對賬與記賬&#xff1a;OCR自動提取交易日期、金額、賬號等信息…

React的介紹和特點

1. React是什么&#xff1f; 1.1. React&#xff1a; 用于構建用戶界面的JavaScript庫1.2. React的官網文檔&#xff1a;https://zh-hans.reactjs.org/ 2. React的特點2.1. 聲明式編程&#xff1a; 目前整個大前端開發的模式&#xff1a;Vue、React、Flutter、SwiftUI只需要維護…

內核smmu學習

思考 smmu對外提供功能&#xff0c;設備驅動調用smmu 提供的api來配置頁表&#xff0c;那其他設備是如何和smmu交互的&#xff1f;iommu 作為將不同smmu硬件的一個抽象封裝&#xff0c;其它設備應該只能看到iommu這個封裝層&#xff0c;那么iommu這個子系統是如何進行抽象的&a…

Android Slices:讓應用功能在系統級交互中觸手可及

引言 在當今移動應用生態中&#xff0c;用戶每天要面對數十個甚至上百個應用的選擇&#xff0c;如何讓自己的應用在關鍵時刻觸達用戶&#xff0c;成為開發者面臨的重要挑戰。Google在Android 9 Pie中引入的Slices技術&#xff0c;正是為了解決這一痛點而生。本文將全面介紹And…

python學智能算法(三十))|SVM-KKT條件的數學理解

【1】引言 前序學習進程中&#xff0c;通過類比力的平衡對KKT條件進行了初步的理解。 今天我們更進一步&#xff0c;常使用數學語言進一步解釋KKT條件。 【2】帶約束的最小優化問題 首先定義一個即將求解的優化問題&#xff1a; 目標函數&#xff1a;最小化f(x)(x∈Rn)f(x)(…

華為云Flexus+DeepSeek征文|Linux命令實現兩種部署的性能捕獲+(硅基+Maas)模型添加教學

前引&#xff1a;“在數字化浪潮洶涌澎湃的今天&#xff0c;企業對云計算服務的需求已從基礎架構支撐&#xff0c;逐步轉向更深層次的AI賦能與業務創新驅動。面對復雜多變的市場環境&#xff0c;選擇一個強大、可靠且具備前瞻性的云服務伙伴&#xff0c;無疑是企業實現高速增長…

langchain--1--prompt、output格式、LCEL示例

環境&#xff1a;本地使用ollama部署的deepseek-r1:1.5b模型 本文示例包含: [1] 非LCEL的調用方法[2] LCEL的調用方法[3] prompt template的簡單使用&#xff0c;除了PromptTemplate模板&#xff0c;還有一些其它模板&#xff0c;可去查看官網[4] 輸出&#xff1a;json格式、py…

【算法】指數滑動濾波器

指數滑動濾波器作用原理特點公式代碼優化升級作用 首先這個濾波器能夠將一些突變的信號對系統的影響降低&#xff0c;能夠平滑輸入信號&#xff0c;濾除噪聲&#xff0c;減少測量數據的瞬間波動和干擾&#xff0c;就是實現輸入信號不能不變&#xff0c;數值不會突然變大&#…

STM32F4—電源管理器

Power supply schemesPower supply supervisorInternal reset ON有PDR_ON pin的MCU&#xff0c;PDR_ON pin被拉高的時候電源監視器被使能。沒有PDR_ON pin的MCU默認一直使能。內部集成了power-on reset (POR) / power-down reset (PDR)POR&#xff08;上電復位&#xff09;&…

MySQL鎖的分類 MVCC和S/X鎖的互補關系

各位看官&#xff0c;大家早安午安晚安呀~~~如果您覺得這篇文章對您有幫助的話歡迎您一鍵三連&#xff0c;小編盡全力做到更好 歡迎您分享給更多人哦今天我們來學習&#xff1a;MySQL鎖的分類 && MVCC和S/X鎖的互補關系1.鎖分類1.按鎖粒度分類&#xff1a;全局鎖&#…

第五屆智能通信與計算國際學術會議(ICICC 2025)

重要信息 官網&#xff1a;www.ic-icc.org 時間&#xff1a;2025年8月15-16日 地點&#xff1a;中國 南京 第五屆智能通信與計算國際學術會議(ICICC 2025&#xff09;定于2025年8月15-16日在中國 南京舉行。隨著信息技術的飛速發展&#xff0c;智能通信與計算領域的研究與…

基于C#和NModbus4庫實現的Modbus RTU串口通信

基于C#和NModbus4庫實現的Modbus RTU串口通信&#xff0c;包含完整的界面設計和功能實現&#xff1a;一、項目依賴配置NuGet包安裝&#xff1a; Install-Package NModbus4 Install-Package System.IO.Ports窗體控件布局&#xff1a; <!-- 基礎控件配置 --> <ComboBox …

想要批量提取視頻背景音樂?FFmpeg 和轉換器都安排上

你是否遇到過這樣的情況&#xff1f;看到一個超贊的短視頻&#xff0c;里面的背景音樂特別好聽&#xff0c;想單獨保存下來當手機鈴聲或收藏&#xff0c;卻不知道怎么把音樂從視頻里“摳”出來&#xff1f;別擔心&#xff01;今天就為大家分享兩種簡單易行的方法&#xff0c;無…

為什么MCP協議是AI集成的未來API

一、企業AI應用的核心挑戰與架構演進 當前企業AI落地面臨三大核心痛點&#xff1a; ??系統集成困境??&#xff1a;需對接企業內部業務系統&#xff08;CRM/ERP等&#xff09;??異構環境兼容??&#xff1a;需整合第三方AI服務與傳統API??數據孤島突破??&#xff1…

Apache Tomcat樣例目錄session操縱漏洞解讀

【漏洞名稱】&#xff1a;Apache Tomcat樣例目錄session操縱漏洞 &#xff08;Apache Tomcat示例目錄漏洞&#xff09;【漏洞等級】&#xff1a;中危&#xff0c;5.9分。【漏洞描述】Apache Tomcat默認安裝頁面中存在examples樣例目錄&#xff0c;里面存放著Servlets、JSP、Web…