一个 unity 节点坐标的简单例子
我先举一个简单的例子,介绍下 Unity 里节点的 Transform 组件的位置,如图一所示我在场景里加了一个 Orthographic摄像机及三个 GameObject,其中摄像机的 size 设为1,三个节点中GameObject1 在顶部中点,GameObject2 在中心点,GameObject3 在左侧中点。
图一,添加三个 GameObject节点的场景
图二展示了他们的位置信息,其中 GameObject1 和 GameObject2 的位置倒是不难理解,由此也可以知道对于 unity 来说中心点的位置是 <0, 0, 0>,顶部的位置是 <0, 1, 0>。图一红框中我们设置的摄像机的 size 为1,因此也可以知道其代表的是场景里摄像机的 height / 2的高度,但是左侧的 GameObject3 的位置为什么是 <-1.505, 0, 0> 呢?其实这是因为我们的摄像机可视区域本来就是个长方形(在 Game window 设置的分辨率会影响 scene window 的摄像机可视区域大小),我在Game window设置的分辨率是 960/640,如果有两个长宽比相等的长方形,一个长/2是x,宽/2是1,另一个长是960,宽是640,我们很容易算出 x 是 1.5(有点误差,是因为我拖 GameObjet3 的时候用眼睛去对齐位置的),当然也很容易知道 unity 的 x 轴是向右为正的。
图二,三个GameObject的位置信息
一个 NGUI 子节点坐标的简单例子
图三展示了一个简单的 NGUI 界面,里面有三个 Widget,位置依次在顶部中点,中心点和左侧中点:
图三,添加三个Widget的NGUI界面
图四展示了三个 Widget 的位置信息:
图四,三个 Widget 的位置信息
问题及结论
对比 unity 节点位置和 NGUI 子节点位置,可以发现即便摆放位置一样,中心点也没改变,顶部中点和左侧中点位置的大小差异却很大,当然通过 widget2 和 widget3 的位置可以得到摄像机可视区域的 height / 2 是320,width / 2 是 480,从而能得出摄像机的可视区域大小恰好是 UIRoot 上设置的分辨率 960/640(这里不考虑分辨率适配的问题,所以 game window 的分辨率是 960/640,UIRoot节点上设置的分辨率也是960/640,UIRoot的设置请参考附录一)。
那么 NGUI 是如何实现这种效果的?看看 UIRoot 的代码,不难发现 NGUI 是通过缩放 UIRoot 的大小来实现这样的效果的,代码一展示了 UIRoot 里 Update 方法的一段代码,这段代码将 UIRoot 缩放了 2 / activeHeight(这个 height 相当于 UIRoot 里设置的 height,为了适配不同分辨率做了一些变换)。
if (calcActiveHeight > 0f ){ float size = 2f / calcActiveHeight; Vector3 ls = mTrans.localScale; if (!(Mathf.Abs(ls.x - size) <= float.Epsilon) || !(Mathf.Abs(ls.y - size) <= float.Epsilon) || !(Mathf.Abs(ls.z - size) <= float.Epsilon)) { mTrans.localScale = new Vector3(size, size, size); }}
代码一,UIRoot 里 Update 方法中的一段代码
这样做的好处应该就是排列 UI 时计算位置方便,相比 unity 坐标 -1~1 的范围,排列 UI 坐标一定是一堆的小数,设计和维护都比较麻烦,NGUI 的这种设计就比较省心。
附录
图五,UIRoot 的设置信息