unity image 调整图层_Graphic


前言

最近开始参与开发一个moba类型的游戏,其中就遇到了要制作雷达图的选手能力展示,所以开始研究异形图片是如何生成的。

在游戏的开发中,开发人员可以根据需求拖拽不同形状的图片到Image的source image中完成对画面的装饰,比如这样


unity image 调整图层_Graphic_02


这些图片是我在ppt里取下来,用在unity的image上,确实通过这样的一种方式可以满足画面的装饰取材需要。

但是,开发无止境,要求不仅仅局限于有了这样一张图片而已,在一些开发中甚至要求图片的一些边边角角能够单独的活动起来,就比如雷达图,用于显示一个人在几种特性的时候根据自己的属性来变化雷达图中个点到中心的距离,因此要求开发中使用的图片是点可控的。

通过流量unity的asset store,可以发现里面是有相关的插件的,但好的居然要钱,所以现在我们自己来试着开发,这是效果的图片。


unity image 调整图层_三角面片_03


因为是基于ugui的组件来开发的,所以我们从组件出发。
在unity中不管是图片还是模型其实都是由三角面片组成,因此只要能够控制三角面片的生成和组合就可以满足我们的需要。

OnPopulateMesh,里面的VertexHelper定义了点的生成和边(edge)的生成。

具体的操作主要包括了vh.addvert和vh.addtriangle两部分组成,前者负责生成点,后者负责将点连成边,再连成三角形。以下是简单的红色三角形图片的操作代码


private void OnPopulateMesh(VertexHelper vh)
    {
        vh.Clear();
        vh.AddVert(new Vector3(0, 0), Color.red, Vector2.zero);
        vh.AddVert(new Vector3(0, 100), Color.red, Vector2.zero);
        vh.AddVert(new Vector3(100, 100), Color.red, Vector2.zero);

        vh.AddTriangle(0, 1, 2);

    }


当然事情不可能这么简单,加入你要生成一个比较复杂的图片,比如说点数相对来说比较多,一个一个自己写是不是太麻烦了,而且在我的雷达图项目中点的坐标必须要不停的更改,那么这样的方法就段段不可取。

unity本身为了解决这种麻烦,设置了vh.AddUIVertexTriangleStream的方法,可以快速的根据vertex的list生成一群三角面片,并将面片组合起来达成我们想要的图案。

那既然有这么一种方法,我们就可以将目标集中到如何按照需求去生成一定数量的点,以下是我写的,可以在inspect面板中生成我们需求中的图片,并且通过半径操作可以到达我们对这个图片中各点位置的实时改变来度量人的能力值。

最后在update函数中写上SetVerticesDirty来在游戏运行中更新点的实时变化,于是项目的初步草稿需求就这样做完了。

demo代码


public class x : Graphic
{
    private List<Vector2> vertexList = new List<Vector2>();
    //雷达图的半径
    public float radius = 5f;

    public float[] diameters=new float[5];

    private void Update()
    {
        //实时刷新各顶点的变化
        SetVerticesDirty();
    }

    protected override void OnPopulateMesh(VertexHelper vh)
    {

        base.OnPopulateMesh(vh);
        vh.Clear();

        for (int i = 0; i < vertexList.Count; i++)
        {
            vertexList[i] = new Vector2(Mathf.Cos(Mathf.PI*2 / vertexList.Count * i) * diameters[i], Mathf.Sin(Mathf.PI*2 / vertexList.Count * i) * diameters[i]);
        }

        List<UIVertex> targetVertexList = new List<UIVertex>();
        int triangleCount = diameters.Length - 2;

        for (int i = 0; i < triangleCount; i++)
        {
            for (int j = 0; j < 3; j++)     
            {
                UIVertex vertex = new UIVertex();
                if (j == 0)
                {
                    vertex.position = vertexList[0];
                }
                else
                {
                    vertex.position = vertexList[i + j];
                }
                vertex.color = color;
                targetVertexList.Add(vertex);
            }
        }

        vh.AddUIVertexTriangleStream(targetVertexList);
    }