本文记录一些Unity中可能用到的坐标变换的方法,包括在C#脚本中及在ShaderLab中:
CS脚本中
在C#脚本中会用到的坐标转换:
local(parent) -> world
本地坐标和世界坐标的转化,local实际上就是此对象的父节点空间,以下三行代码都会输出该GameObject的世界坐标(有父节点的情况下):
1 | Debug.Log(transform.position); |
world -> local(parent)
将世界坐标转换为本地坐标,以下三行代码都会输出该GameObject的本地坐标(有父节点的情况下):
1 | Debug.Log(transform.localPosition); |
如果需要计算某对象在另一个空间中的坐标,可通过local->world->someparent转换,也可以得出相对于父节点的变换矩阵,逐级变换:
逐级变换
假设现在有四个GameObject对象,它们的分别被引用为t1、t2、t3和t4:
1 | public Transform t1; |
设置它们的父子关系如下:
1 | t4.SetParent(t3, false); |
使用m1、m2和m3来保存t1、t2和t3 的变换矩阵(TRS),则可以看到下边的三个Debug.Log都会输出t4的世界坐标(t1有父节点):
1 | Debug.Log(t4.position); |
将t4连续的施以m3、m2和m1,即可得到t4在t1.parent之下的局部坐标。
shader中
在顶点着色器中常常会使用一些变换,如下:
local -> world
本地坐标到世界坐标的转换,借助于内置变量unity_ObjectToWorld,旧版本中叫做_Object2World,将本地坐标pos转换到为世界坐标的方法如下:
1 | mul(unity_ObjectToWorld, float4(pos, 1.0)); |
world -> local
世界坐标到本地坐标的转换,借助于内置变量unity_WorldToObject,旧版本中叫做_World2Object,将世界坐标pos转换到为本地坐标的方法如下:
1 | mul(unity_WorldToObject, float4(pos, 1.0)); |
obj -> clip
最常用到的还是本地坐标到裁剪空间的坐标转换,如将本地坐标pos转化为裁剪屏幕的坐标,可以调用第一行的函数,也可以使用第二行的矩阵乘法,Unity似乎会自动把mul(UNITY_MATRIX_MVP, *)转化成前者:
1 | float4 UnityObjectToClipPos(float3 pos); |
REFERENCE
https://docs.unity3d.com/Manual/class-Transform.html
https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html