UG4L12——坐标系统
UG4L12——坐标系统
本章代码关键字
1 | gObject.LocalToGlobal() //输出元件在FGUI坐标系下的物理屏幕坐标 |
FairyGUI的坐标原点
FairyGUI是以屏幕左上角为原点的,Unity的屏幕坐标是以左下角为原点
如果想转化屏幕坐标和UI坐标:
1 | void Update() |
输出:
UI对象和屏幕坐标转换
在FGUI我们会与三种屏幕坐标打交道:
- 相对于父元件的局部坐标
- 相对于FGUI坐标系的实际在屏幕上显示的物理屏幕坐标(由于分辨率自适应的存在很可能与逻辑屏幕坐标不一致)
- 相对于FGUI坐标系的FGUI元件真正参与计算的逻辑屏幕坐标(和FGUI编辑器设置的位置一致)
-
GObject
里的x/y/position
值都是局部坐标,也就是相对于父元件的偏移
1
2
3
4
5
6
7
8
9
10
11
12
13void Start()
{
//显示面板组件的方法
TeachPanel panel = UIManager.Instance.ShowPanel<TeachPanel>("teach");
//图形相对于面板组件的局部坐标
print(panel.m_graphTest.x);
print(panel.m_graphTest.position);
GObject obj = panel.m_svTest.GetChild("n1");
//面板下的滚动视图中的第二个格子相对于滚动视图组件的局部坐标
print(obj.x);
print(obj.y);
print(obj.position);
}输出:
对比其在FairyGUI编辑器显示的坐标:
-
获取任何一个元件在屏幕上的坐标(FairyGUI坐标系下,左上角原点,不常用)
该方法的参数和返回值可以是
Vector2
也可以是Rect
,
传入的Vector2
参数代表的是与元件锚点的偏移量,如果只是获取位置只需要传入Vector2.zero
即可值得一提的是,该方法得到的是该元件在物理屏幕上的坐标,由于屏幕的分辨率和FGUI处理的设计分辨率不一致,
因此这里得到的坐标很可能与在FairyGUI编辑器处设置的元件坐标不一致,该坐标不适用于直接与FGUI相关元件交互
1
2
3
4
5
6
7
8//显示面板组件的方法
TeachPanel panel = UIManager.Instance.ShowPanel<TeachPanel>("teach");
//面板下的滚动视图中的第二个格子相对于滚动视图组件的局部坐标
GObject obj = panel.m_svTest.GetChild("n1");
print("局部坐标" + obj.position);
//转换为FGUI坐标系下的坐标
Vector2 screenPos = obj.LocalToGlobal(Vector2.zero);
print("相对于FGUI屏幕坐标系的坐标" + screenPos);输出:
-
获取屏幕坐标在UI元件上的局部坐标(不常用)
注意,这里的屏幕坐标指的是在物理屏幕上的坐标,而非FGUI计算所采用的逻辑屏幕(设计分辨率)的坐标
1
2
3
4
5
6
7
8
9
10GObject obj = panel.m_svTest.GetChild("n1");
print(obj.x);
print(obj.y);
print("局部坐标" + obj.position);
//把局部坐标转为实际屏幕坐标
Vector2 screenPos = obj.LocalToGlobal(Vector2.zero);
print("相对于FGUI屏幕坐标系的坐标" + screenPos);
//把实际屏幕坐标转为局部坐标
Vector2 localPos = obj.GlobalToLocal(screenPos);
print("通过FGUI坐标系下的屏幕坐标 转为 相对于某个对象内部的局部坐标" + localPos);输出:
-
物理屏幕坐标转换为逻辑屏幕坐标
如果UI适配导致全局缩放,那么逻辑屏幕大小和物理屏幕大小不一致,逻辑屏幕坐标就是GRoot里的坐标
编辑器里定义和代码中处理的 指的都是逻辑屏幕坐标(UI坐标)而gObject.LocalToGlobal()输出的都是物理屏幕坐标,此方法获取的坐标不适合直接用于FGUI相关元件交互,
例如在某个元件的位置上再添加一个元件,就不适用,需要将其转换为逻辑屏幕坐标
实际Unity编辑器下的物理屏幕分辨率为
而FairyGUI编辑器下的逻辑屏幕分辨率为1
2
3
4
5
6
7
8
9
10
11//显示面板组件的方法
TeachPanel panel = UIManager.Instance.ShowPanel<TeachPanel>("teach");
//面板下的滚动视图中的第二个格子相对于滚动视图组件的局部坐标
GObject obj = panel.m_svTest.GetChild("n1");
print("局部坐标" + obj.position);
//把局部坐标转为实际屏幕坐标
Vector2 screenPos = obj.LocalToGlobal(Vector2.zero);
print("相对于FGUI屏幕坐标系的物理屏幕坐标" + screenPos);
//把物理屏幕坐标转换为逻辑屏幕坐标
Vector2 logicalPos = GRoot.inst.GlobalToLocal(screenPos);
print("相对于FGUI屏幕坐标系的逻辑屏幕坐标" + logicalPos);输出:
对比FairyGUI编辑器设置的位置:
-
UI元件坐标与逻辑屏幕坐标之间的转换
gObject.LocalToRoot()
可以直接将局部坐标转换为FGUI计算会使用的逻辑屏幕坐标(第二个参数必须传入GRoot.inst
)
该方法得到的坐标可以直接参与FGUI元件的交互,因此它最常用如果要将逻辑屏幕坐标转换为相对于父元件的局部坐标,需要使用
gObject.RootToLocal()
(第二个参数必须传入GRoot.inst
)
1
2
3
4
5
6
7TeachPanel panel = UIManager.Instance.ShowPanel<TeachPanel>("teach");
//面板下的滚动视图中的第二个格子相对于滚动视图组件的局部坐标
GObject obj = panel.m_svTest.GetChild("n1");
print("局部坐标" + obj.position);
Vector2 logicalScreenPos = obj.LocalToRoot(Vector2.zero, GRoot.inst);
print("对象相对屏幕的逻辑坐标" + logicalScreenPos);
print("逻辑坐标转换为局部坐标" + obj.RootToLocal(logicalScreenPos, GRoot.inst));输出:
对比FairyGUI编辑器设置的位置:
-
A中相对坐标相对B的位置
- 参数一:相对于自己的某个坐标
- 参数二:要计算相对于哪个元件的位置
1
2
3
4
5
6
7
8
9
10
11TeachPanel panel = UIManager.Instance.ShowPanel<TeachPanel>("teach");
//图形相对于面板组件的局部坐标
print(panel.m_graphTest.x);
print(panel.m_graphTest.position);
//面板下的滚动视图中的第二个格子相对于滚动视图组件的局部坐标
GObject obj = panel.m_svTest.GetChild("n1");
//计算相对于B的位置
Vector2 relativeToBPos = obj.TransformPoint(Vector2.zero, panel.m_imgTest);
print("A中相对位置(0,0)相对于B的位置" + relativeToBPos);
relativeToBPos = obj.TransformPoint(new Vector2(10, 10), panel.m_imgTest);
print("A中相对位置(10,10)相对于B的位置" + relativeToBPos);输出:
对比FairyGUI编辑器设置的位置:
计算A中相对位置
(0, 0)
相对于B的位置:
计算A中相对位置(10, 10)
相对于B的位置:
世界坐标转换
-
世界坐标转UI坐标
世界 ——> 屏幕 ——> UI
假设要得到下面的Cube对象相对于FairyGUI坐标系的逻辑屏幕坐标(UI坐标)
1
2
3
4
5
6
7//得到相对于Unity坐标系的物理屏幕坐标
Vector2 screenPos = Camera.main.WorldToScreenPoint(this.transform.position);
//得到相对于FairyGUI坐标系的物理屏幕坐标
screenPos.y = Screen.height - screenPos.y;
//得到FairyGUI直接使用计算的逻辑屏幕坐标
Vector2 logicalPos = GRoot.inst.GlobalToLocal(screenPos);
print("Cube在相对于FairyGUI坐标系的逻辑屏幕坐标(UI坐标)位置" + logicalPos);输出:
-
UI坐标转世界坐标
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17print("世界坐标" + this.transform.position);
//得到相对于Unity坐标系的物理屏幕坐标
Vector3 screenPosVector3 = Camera.main.WorldToScreenPoint(this.transform.position);
float distance = screenPosVector3.z;
//得到相对于FairyGUI坐标系的物理屏幕坐标
screenPosVector3.y = Screen.height - screenPosVector3.y;
//得到FairyGUI直接使用计算的逻辑屏幕坐标
Vector2 logicalPos = GRoot.inst.GlobalToLocal(screenPosVector3);
print("Cube在相对于FairyGUI坐标系的逻辑屏幕坐标(UI坐标)位置" + logicalPos);
//将逻辑屏幕坐标转换为相对于FairyGUI坐标系的物理屏幕坐标
screenPosVector3 = GRoot.inst.LocalToGlobal(logicalPos);
//得到相对于Unity坐标系的屏幕坐标
screenPosVector3.y = Screen.height - screenPosVector3.y;
//一般情况下,还需要提供距离摄像机视野正前方distance长度的参数作为screenPos.z(如果需要,将screenPos改为Vector3类型)
screenPosVector3.z = distance;
Vector3 worldPos = Camera.main.ScreenToWorldPoint(screenPosVector3);
print("从逻辑屏幕坐标转换为世界坐标" + worldPos);输出: