前言

本文会详细介绍三维软件中 7 种坐标的特点与关系,还有在脚本编辑和 shader 系统中的使用方法后续更新

正文

不同空间中坐标的转换方法

七种坐标系简介

unity 使用的是左手坐标系,即:
↑=Y,↓=-Y,前 = Z,后 =-Z,←=-X,→=X。
总共有七种坐标系,分别是模型坐标、世界坐标、观察坐标、裁剪坐标、屏幕坐标、ui 坐标,uv 坐标这七种坐标会按照一定顺序转换在程序中运行,实际上这就是模型从计算到在屏幕上显示的过程。

一 模型坐标

Local Space (模型坐标):就是一个模型自己的坐标,如果该模型下有子模型,则子模型也拥有自己的模型坐标,多个子模型在父模型下共享父坐标。
坐标:
模型原点为(0,0)
需要说明的是一个模型坐标的原点位置在创建模型的时候就定义好了。如果需要更改只能在 blender 或 3dmax 等建模软件中设定。unity 是不能设置模型坐标原点的。
获取方式:
在 unity 脚本中:
transform.localPosition
在 unity shader 中:
顶点着色器默认输入的就是模型坐标

二 世界坐标

World Space(世界坐标):场景中的一切物体,包括模型,灯具,相机都共享一个绝对位置,这就是世界坐标。所有在模型坐标中的变化最终都会映射到世界坐标中。
坐标:
世界的中心点:0,0
获取方式:
在 unity 脚本中:
使用 transform.position 可以获得该位置坐标。
在 unity shader 中:
需要 将模型坐标转换为世界坐标才能获得。

三 观察坐标(视口坐标)

ViewPort Space (观察坐标):每个相机都是一个观察者,每个观察者都有自己的视界。
到这一步,会把世界坐标转换为以摄像机为参考的原点和方向。
坐标:
左下角为(0,0)
右上角为(1,1)
Z 的位置是以相机的世界单位来衡量的。
获取方式:

四 裁剪坐标

Clip Space (裁剪坐标):裁剪坐标是将观察世界的一部分截取出来。摄像机在取景的时候使用一个六面体去处理可视的区域,所有在这个区域的物体才会被显示。那么你肯定会有以为,为什么不直接用观察坐标,为什么一定要用这个裁剪呢? 首先,相机有两种模式,即透视相机与正交镜头(没有近大远小的透视效果)。这两种模式的切换会在裁剪坐标中处理。其次裁剪坐标规定了那些模型计算后可以显示,那些模型计算后但不用显示。所以必须有这个步骤。

五 屏幕坐标

Screen Space(屏幕坐标): 屏幕坐标用于将裁剪坐标中的物体信息映射到屏幕上。我们知道三维世界是立体的,但不管是几维世界,只要实在屏幕上显示的就一定是 2d 的。
坐标:
左下角为(0,0)点
右上角为(Screen.width,Screen.height)
获取方式:
Z 的位置是以相机的世界单位来衡量的。
  Screen.width = Camera.pixelWidth
  Screen.height = Camera.pixelHeigth

六 ui 坐标

ui 坐标是特殊的坐标系统,专门用于处理 ui 组件。ui 坐标系是可视化窗口的最顶层,世界坐标系的物体都会被 ui 坐标系遮挡。
坐标:
左下角为(0,0)点
右上角为(Screen.width,Screen.height)
Z 轴影响显示层级位置
获取方式:

七 uv 坐标

相比之前的六种坐标系,uv 坐标系只负责定位贴图和模型的关系
坐标:
左下角为(0,0)
右上角为(1,1)
获取方式:

【坐标系的转换】

1、世界坐标→屏幕坐标:

camera.WorldToScreenPoint(transform.position); 这样可以将世界坐标转换为屏幕坐标。其中 camera 为场景中的 camera 对象。

1
2
3
4
5
6
7
8
9
10
11
public class Follow_2d3d : MonoBehaviour
{
public GameObject f2d;
public GameObject f3d;
void Update()
{
Vector3 pos_3d = f3d.transform.localPosition;
Vector3 screen_point = gameObject.GetComponent<Camera>().WorldToScreenPoint(pos_3d);
f2d.transform.position = screen_point;
}
}

该代码实现效果:ui 中的 2d 元素会与三维物体重合,移动三维物体,2d 元素会跟着移动

2、屏幕坐标→视口坐标:

camera.ScreenToViewportPoint(Input.GetTouch(0).position); 这样可以将屏幕坐标转换为视口坐标。其中 camera 为场景中的 camera 对象。

1
2
3
4
5
6
7
8
9
10
11
public class Follow_2d3d : MonoBehaviour
{
public GameObject f2d;
public GameObject f3d;
void Update()
{
Vector3 pos_2d = f2d.transform.position;
Vector3 world_point = gameObject.GetComponent<Camera>().ScreenToWorldPoint(pos_2d);
f3d.transform.position = world_point;
}
}

该代码实现效果:ui 中的 2d 元素会与三维物体重合,移动 2d 元素,三维物体会跟着移动

3、视口坐标→屏幕坐标:

camera.ViewportToScreenPoint();

4、视口坐标→世界坐标:

camera.ViewportToWorldPoint();
鼠标拖拽 ui,不能直接使用 position 赋值。需要通过相机转换。


参考链接:[ unity 七种坐标系统详解与互相转换的方法 模型坐标、世界坐标、观察坐标(视口坐标)、裁剪坐标、屏幕坐标、ui 坐标、uv 坐标 ]


to be continued…