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;

浙公网安备 33010602011771号