前言

本文会详细介绍三维软件中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…