Unity坐标系与坐标转换

Unity 坐标系与坐标转换

1. Unity 中的四大坐标系

Unity 中最常用的坐标系有 4 类,各自独立但可以互相转换。

1. 世界坐标(World Space)

代表整个场景的绝对坐标。

用途:

  • 3D 物体位置、旋转、缩放
  • 物体之间距离/方向计算
  • 相机、角色移动
transform.position
transform.rotation
transform.eulerAngles
transform.lossyScale

2. 本地坐标(Local Space)

物体相对于父对象的位置和旋转。

用途:

  • 子物体跟随
  • 局部旋转(例如枪口抬起)
  • 骨骼动画
transform.localPosition
transform.localRotation
transform.localEulerAngles
transform.localScale

3. 屏幕坐标(Screen Space)

单位:像素
原点:左下角

用途:

  • 获取鼠标位置
  • 屏幕 UI 定位
  • 射线检测 Input.mousePosition
Input.mousePosition; 
Screen.width;
Screen.height;

4. 视口坐标(Viewport Space)

Camera组件的Viewport Rect参数
单位:0 ~ 1
原点:左下角
与分辨率无关。

用途:

  • 判断物体是否进入视野
  • 制作屏幕边缘提示箭头
  • UI 指向视野外目标

2. 坐标转换(按使用频率排序)

✔ 1. 世界 ↔ 本地

本地 → 世界

//本地坐标系点转世界坐标系点 受缩放影响
Vector3 worldPos = transform.TransformPoint(localPos);
//本地坐标系方向转世界坐标系方向 不受缩放影响
Vector3 worldDirection = transform.TransformDirection(localDiretion);
//本地坐标系方向转世界坐标系方向 受缩放影响
Vector3 worldVector = transform.TransformVector(localVector3);

用途:

  • 局部偏移转换成世界位置
  • 生成子物体时定位

世界 → 本地

//世界坐标系点转本地坐标系点 受缩放影响
Vector3 localPos = transform.InverseTransformPoint(worldPos);
//世界坐标系方向转本地向量 不受缩放影响
Vector3 localDirection = transform.InverseTransformDirection(worldDirection);
//世界坐标系方向转本地向量 受缩放影响
Vector3 localVector = transfrom.InverseTransformVector(worldVector3);

用途:

  • 判断一个 3D 点相对于某物体的方向(但是一般用点乘)
  • 子物体跟父物体运动

✔ 2. 世界 ↔ 屏幕

世界 → 屏幕(UI 跟随 3D 物体)

Vector3 screenPos = Camera.main.WorldToScreenPoint(worldPos);

用途示例:

  • 在敌人头上显示血条
  • 指示器 UI 跟随 3D 角色

屏幕 → 世界(鼠标点击 3D 物体)

Vector3 pos = Input.mousePosition;
pos.z = 10; // 相机到目标的距离
Vector3 worldPos = Camera.main.ScreenToWorldPoint(pos);

用途示例:

  • 鼠标控制物体移动
  • 鼠标选中场景中的物体

✔ 3. 世界 ↔ 视口

世界 → 视口

Vector3 v = Camera.main.WorldToViewportPoint(pos);

用途:

  • 判断是否在屏幕内:
    if (v.x >= 0 && v.x <= 1 && v.y >= 0 && v.y <= 1)
    
  • 制作屏幕边缘箭头指向目标

视口 → 世界

Camera.main.ViewportToWorldPoint(viewPos);

用途:

  • 在屏幕某个比例位置生成物体
  • 如左上角 = (0, 1)

3. UI(RectTransform)与屏幕坐标转换

UI 使用 RectTransform 坐标系,不能直接用世界坐标或屏幕坐标。
因此拖拽、跟随 UI 必须使用:

屏幕坐标 → UI 本地坐标

Vector2 uiPos;
RectTransformUtility.ScreenPointToLocalPointInRectangle(
    parentRect,
    screenPoint,
    eventData.pressEventCamera, // 推荐使用,避免 null
    out uiPos
);

用途:

  • UI 拖拽
  • 点击 UI 显示动作
  • 界面图标跟随鼠标

为什么用 pressEventCamera 而不是 enterEventCamera

  • enterEventCamera 在鼠标离开 UI 时会变 null(导致坐标转换失败)
  • pressEventCamera 在按下 → 拖拽过程中一直有效
  • 多 Canvas、多 Camera 下更稳定

4. 最常用的 API 整理(速查表)

功能 API
本地 → 世界 transform.TransformPoint
世界 → 本地 transform.InverseTransformPoint
世界 → 屏幕 Camera.main.WorldToScreenPoint
屏幕 → 世界 Camera.main.ScreenToWorldPoint
世界 → 视口 Camera.main.WorldToViewportPoint
视口 → 世界 Camera.main.ViewportToWorldPoint
屏幕 → UI 本地 RectTransformUtility.ScreenPointToLocalPointInRectangle

5. 经典使用场景

✔ 场景 1:鼠标点一个 3D 物体

Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out RaycastHit hit))
{
    Debug.Log(hit.collider.name);
}

✔ 场景 2:UI 图标跟随 3D 敌人头顶

Vector3 pos = Camera.main.WorldToScreenPoint(enemy.position);
uiRect.position = pos;

✔ 场景 3:拖拽 UI

RectTransformUtility.ScreenPointToLocalPointInRectangle(
    (RectTransform)transform.parent,
    eventData.position,
    eventData.pressEventCamera,
    out Vector2 localPos
);
transform.localPosition = localPos;
posted @ 2025-11-30 18:31  高山仰止666  阅读(19)  评论(0)    收藏  举报