UGUI气泡的遮挡问题研究与解决
在Unity中做血条或者悬浮气泡会有一个小问题是我们需要解决的,这就是遮挡顺序的问题。
用过的大家都知道,UI的顺序是以在面板中的层次顺序来排列的。下面举个例子。
在unity中搭建一个场景,如下图所示:
建三个小球,分别配上三个不同颜色的材质,建三个image分别给三个颜色,一一对应。
然后写一个跟随的脚本,让三个UI分别悬浮到三个小球上方,为了快速,用最简单的方式来写
到这一步后还不够,还得接着来修改一些东西:
1)修改如图的canvas
2)把三个UI image的大小(高和宽)改小一点,不然就太大了,改成15差不多了。如图:
然后点击运行,查看效果,改变相机的位置和朝向,截取两张图做对比,如下图:
VS
大家可以看到第一张图是对的,第二张图从另一半看就错了,有了遮挡。
再看一张层次图:
层次图里aaaa\bbbb\cccc的顺序是不会变的。
然而我们要做的事就是通过一定判断改变它的顺序,按照我们想要的顺序来改变。
用过的大家都知道,UI的顺序是以在面板中的层次顺序来排列的。下面举个例子。
在unity中搭建一个场景,如下图所示:
建三个小球,分别配上三个不同颜色的材质,建三个image分别给三个颜色,一一对应。
然后写一个跟随的脚本,让三个UI分别悬浮到三个小球上方,为了快速,用最简单的方式来写
如下:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.EventSystems; public class abc : MonoBehaviour { public Transform aa; public Transform bb; public Transform cc; public RectTransform aaa; public RectTransform bbb; public RectTransform ccc; // Use this for initialization void Start () { } // Update is called once per frame void Update () { aaa.transform.position = new Vector3(aa.position.x, aa.position.y + 5.0f, aa.position.z); bbb.transform.position = new Vector3(bb.position.x, bb.position.y + 5.0f, bb.position.z); ccc.transform.position = new Vector3(cc.position.x, cc.position.y + 5.0f, cc.position.z); } }然后把该脚本绑到相机上,把对应的三个小球和三个UI拖入到对应位置,如下图:
到这一步后还不够,还得接着来修改一些东西:
1)修改如图的canvas
2)把三个UI image的大小(高和宽)改小一点,不然就太大了,改成15差不多了。如图:
然后点击运行,查看效果,改变相机的位置和朝向,截取两张图做对比,如下图:
大家可以看到第一张图是对的,第二张图从另一半看就错了,有了遮挡。
再看一张层次图:
层次图里aaaa\bbbb\cccc的顺序是不会变的。
然而我们要做的事就是通过一定判断改变它的顺序,按照我们想要的顺序来改变。
接着上篇来写,如何改变面板中的层次结构是一个问题,根据什么来判断层次的先后顺序是一个问题,只要解决这两点就OK啦
很简单,unity中其实有一个方法可以通过脚本来改变层次结构,该方法就是SetSiblingIndex;然后根据什么来判断这点,当然是根据物体与摄像机的距离来判断。
我们可以把所需要的物体与摄像机之间的距离计算出来,然后通过距离的大小改变UI的层次索引。
当然,这个方法要放到Update里或者相机有位置改变的时候执行,这样不论相机怎么移动,都会看到距离相机近的物体的UI在最前面,符合实际情况。
Camera cam; float[] deviceToCam = new float[3]; Dictionary<float, RectTransform> floatToUI = new Dictionary<float, RectTransform>(); void test() { cam = Camera.main; deviceToCam[0] = Vector3.Distance(cam.transform.position, aa.position); floatToUI.Add(deviceToCam[0], aaa); deviceToCam[1] = Vector3.Distance(cam.transform.position, bb.position); floatToUI.Add(deviceToCam[1], bbb); deviceToCam[2] = Vector3.Distance(cam.transform.position, cc.position); floatToUI.Add(deviceToCam[2], ccc); Array.Sort(deviceToCam); Array.Reverse(deviceToCam); for (int j = 0; j < 3; j++) { floatToUI[j].SetSiblingIndex(j); } }
上述代码有字典键值的问题,但是意思正确。具体项目中可以用列表、字典等来存放。
另外可以通过两帧之间的差值判断相机的移动,如下:
#region 通过两帧差值判断相机移动 newPos = cam.transform.position; if (oldPos == Vector3.zero) { } else { cha = newPos - oldPos; } oldPos = newPos; #endregion //cha.magnitude if(cha.magnitude > 0.00001f) { test(); }
附上一张图:
相机的移动方式很多,我就不多说了。