UGUI气泡的遮挡问题研究与解决

在Unity中做血条或者悬浮气泡会有一个小问题是我们需要解决的,这就是遮挡顺序的问题。


用过的大家都知道,UI的顺序是以在面板中的层次顺序来排列的。下面举个例子。


在unity中搭建一个场景,如下图所示:


UGUI气泡的遮挡问题研究与解决 



UGUI气泡的遮挡问题研究与解决 



建三个小球,分别配上三个不同颜色的材质,建三个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拖入到对应位置,如下图:
UGUI气泡的遮挡问题研究与解决 



到这一步后还不够,还得接着来修改一些东西:
1)修改如图的canvas
UGUI气泡的遮挡问题研究与解决 



2)把三个UI image的大小(高和宽)改小一点,不然就太大了,改成15差不多了。如图:
UGUI气泡的遮挡问题研究与解决 



然后点击运行,查看效果,改变相机的位置和朝向,截取两张图做对比,如下图:
UGUI气泡的遮挡问题研究与解决 VS UGUI气泡的遮挡问题研究与解决 



大家可以看到第一张图是对的,第二张图从另一半看就错了,有了遮挡。


再看一张层次图:
UGUI气泡的遮挡问题研究与解决 



层次图里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();
        }

附上一张图:
UGUI气泡的遮挡问题研究与解决 



相机的移动方式很多,我就不多说了。