本文章装载字:http://mp.weixin.qq.com/s?__biz=MzAxMDcxOTkxNQ==&idx=1&mid=402542189&sn=682dee9056d5059d5c17edd4e6865295
我们先从一个实际的需求出发。
需求描述:3D游戏中的怪物死亡会随机掉落一个宝箱,当有宝箱掉落时需要实现一个 UI 宝箱效果,从怪物当时所在的屏幕坐标处飞到游戏的宝箱 UI 上,然后宝箱计数加1。
解决思路:
-
宝箱的动画属于 UI层 的东西,需要在 UI 坐标系上进行;
-
需要将怪物的 3D世界坐标 转换成 2D的UI坐标。
为了解决以上问题,我们先来了解一下UGUI中涉及到的坐标系,我把这些坐标系总结为三个类型:屏幕坐标系,UI逻辑坐标系和UI世界坐标系。下面来逐一介绍。
屏幕坐标系
屏幕坐标系是和屏幕分辨率一致的坐标系。
屏幕坐标系以屏幕的左下角为远点,屏幕右上角的坐标是(Screen.width, Screen.height)。示意图如下图所示:
屏幕坐标系的范围和分辨率有关,例如 iPhone4S 就是 960*640, 5S 则是 1136*640等。不同型号设备的分辨率可能不同,因此屏幕坐标系的范围也可能不同。UI 界面显示的时候因为要照顾到不同分辨率的手机,所以不能以屏幕坐标系来进行布局。
UI逻辑坐标系
UI逻辑坐标系是我们在设计UI界面的时候的参考坐标系。
参考坐标系一般对当前流行的手机的分辨率保持一致,例如当前流行的是 iPhone6s 的 2000*1125,则美术在制作界面示意图的时候就需要参考这个分辨率进行制作,保证在当前主流机型上有最佳的显示效果。
uGUI中坐标系的起点和屏幕坐标系是相同的,界面的左下角是原点,size是通过 Canvas 和 Canvas Scalar 组件来确定的。如下图所示。
-
没有 Canvas Scalar 组件
此时 UI逻辑坐标系 == 屏幕坐标系。一般不采用此种用法,除非只想针对一种分辨率设备来做UI或者有自己的屏幕适配方案。
-
有Canvas Scalar
顾名思义,Canvas Scalar 使用 RectTransform 的 localScale 来使得 UI逻辑坐标 * RectTranform.localScale == 屏幕坐标。
Canvas Scalar 有三种 UIScaleMode:
例如屏幕大小变成了 960*640,则 Canvas 的大小便为 960*640。如果设置 ScaleFactor = 2, 则 localScale = new Vector3(2, 2, 2), Canvas 的大小为 480*320。此种设置的具体使用场景还未知。
一般在进行屏幕适配的时候会选择 MatchWidthOrHeight 来进行适配。
在确定了 scale 之后,UI逻辑坐标系的大小 = 屏幕坐标系大小/scale,这样子可以保证UI逻辑坐标系的宽高比(Aspect Ratio)和屏幕坐标系的宽高比相同。
UI世界坐标系
UI世界坐标系是指通过 RectTransfrom.position 获取的坐标值。这个是由 Canvas 组件的 RenderMode 来决定的:
此时通过 Canvas 上的 RectTransfrom 的 localScale 来将 屏幕坐标规约到 UI 坐标区域。
此时如果需要获取需要获取一个UI的屏幕坐标,可以通过下述代码来获得:
一些个人理解
-
Overlay的 RenderMode 该如何选择?
-
如果UI一致显示界面的最高层,那么使用 Screen-Space Overlay 模式即可;如果需要多个 Canvas 可以通过 Sort Order 来进行分成,Sort Order 越大显示越靠前;
-
如果UI中间需要嵌入一个3D物体,例如背景UI在最底层,人物 avatar 显示在中间层,上层显示其他 UI界面,则使用 Screen-Space Camera,此时需要多个 Camera ,然后通过 Camera 的 depth 来控制显示的次序,depth 越大越后渲染,越靠前。另外各个 Camera 的 ClearFlags 需要正确设置,背景的设置为 Solid Color,负责擦屏幕;之后的设置为 Depth Only 即可;
-
如果 UI 界面需要显示在世界中,则需要使用 World Space,例如在 VR 场景中。
-
Canvas Scalar的 UIScaleMode 该怎么选择?怎么可以让UI可以适配所有设备?
这里介绍一下个人使用经验,因为其他用得不多,优点还不知道:
-
UIScaleMode 设置成 ScaleWithScreenSize;
-
Reference Resolution 设置成当前最主流机型的分辨率,同时告诉美术这个就是参照的大小;
-
Match 设置成0或者1,设置成0的时候就是按照宽度适配,则以后宽度不需要考虑适配,高度上进行适配,此时告诉UI在设计UI的时候高度上一定要设置成高度可以调节的;反之亦可。一般建议横屏设置成宽度不变,竖屏设置成高度不变。
-
什么时候用 UI 逻辑坐标系,什么时候用 UI世界坐标系?
在游戏制作过程中拼界面的时候用 UI 逻辑坐标系,这个时候需要使用 RectTransform 提供的 pivot, anchorPos等进行UI的对齐和大小设置;
在使用程序控制UI进行动画的时候最好使用 UI世界坐标系。
引题答案
代码工程放在github[https://github.com/tnqiang/UI_Flow_Effect]上,代码解释:
-
第一步需要将 source 3D 物体从世界坐标转换到屏幕坐标,这个需要3D世界摄像机才能取得;
-
第二步需要将这个屏幕坐标转换到 UI 世界的世界坐标中,这个需要看 Camara 的 RenderMode 是否是 Overlay,如果是则直接是世界坐标,否则需要UI的摄像机来帮助。
Refs:
-
uGUI源代码之CanvasScaler[https:///Unity-Technologies/ui/src/0155c39e05ca5d7dcc97d9974256ef83bc122586/UnityEngine.UI/UI/Core/Layout/CanvasScaler.cs?at=5.2&fileviewer=file-view-default]
|