使用UGUI自定义五边形

using UnityEngine;
using System.Collections.Generic;
using UnityEngine.UI;

/*
 * 
 *           5
 * 
 * 
 *   6       0       4
 * 
 * 
 *      1    2    3
 *      
 * 
 * 
*/

public class UIPropWidget : Graphic
{   
    private const int VERTEX_SIZE = 8;                  // 必须为4的倍数  通过绘制两个四边形组成一个五边形

    private List _currentList = new List();

    private Vector2 vec0 = new Vector2(0, 0);
    private Vector2 vec1;
    private Vector2 vec2;
    private Vector2 vec3;
    private Vector2 vec4;
    private Vector2 vec5;
    private Vector2 vec6;

    private float cos18;
    private float sin18;

    private float cos36;
    private float sin36;

    private float rate = 1f;
    private float radius = 100f;

    void Awake(){
        Init();
    }

    void Update()
    {
        SetVerticesDirty();
    }

    public void Init(){ 

        float angle36 = 36*Mathf.PI/180;
        float angle18 = 18*Mathf.PI/180;

        cos18 = Mathf.Cos(angle18);
        sin18 = Mathf.Sin(angle18);

        cos36 = Mathf.Cos(angle36);
        sin36 = Mathf.Sin(angle36); 

        vec1 =  new Vector2(-radius*sin36*rate, -radius*cos36*rate);
        vec3 =  new Vector2(radius*sin36*rate, -radius*cos36*rate);
        vec4 =  new Vector3(radius*cos18*rate, radius*sin18*rate);
        vec5 =  new Vector3(0, radius*rate);
        vec6 =  new Vector3(-radius*cos18*rate, radius*sin18*rate);

        //通过两点式算出1,3直线与y轴的交点
        vec2 =  new Vector2(0, (0 - vec1.x)/(vec3.x - vec1.x)*(vec3.y - vec1.y) + vec1.y);


        _currentList.Add(vec1);
        _currentList.Add(vec2);
        _currentList.Add(vec5);
        _currentList.Add(vec6);
        _currentList.Add(vec2);
        _currentList.Add(vec3);
        _currentList.Add(vec4);
        _currentList.Add(vec5);

        SetVerticesDirty();
    }


    private void UpdateVertex(List vbo, List list)
    {
        // 必须要保证填充的是4的倍数
        for (int i = 0; i < VERTEX_SIZE; ++i) {
            var vert = UIVertex.simpleVert;
            vert.color = color;
            vert.position = list[i];
            vbo.Add(vert);
        }
    }

    protected override void OnFillVBO(List vbo)
    {       
        UpdateVertex(vbo, _currentList);
    }
}

一个CanvasRenderer进行绘制,所有的控件和可显示的元素都是Graphic。Graphic持有一个canvasRenderer,通过SetVertices设置顶点,最终完成绘制。 举例来说,Image控件就是一个Graphic,这个GameObject上面同时还有一个CanvasRenderer,两者结合起来最终把图片绘制完成。

以五边形中心点为原点,求出五个顶点1, 4, 3, 6, 7以及底边中心点2的位置
因为uGUI的绘制元素是Quad而不是三角形,SetVertices中设置的顶点数目必须是4的倍数,所以用他们组成两个四边形 1,2,3,4和5,6,7,8用这两个四边形组成一个五边形
给的坐标是相对于自己的坐标系的像素坐标(相对于自已的privot)假设我要绘制一个100*100的矩形,privot是(0.5,0.5),四个顶点的坐标则分别为(-50,-50),(50, -50),(50, 50),(-50, 50)

最后补充一些关于vertex设置的知识点。
一个控件的GameObject上面只允许有一个Graphic,所以不可能同时存在Image和Text。 我们自定义形状的控件可以通过两种方式来实现,一种是重载Graphic,这样这个控件就与Image等价,这里有两个比较重要的可以重载的函数 UpdateGeometry和OnFillVBO。如果看下uGUI的源代码可以发现,UpdateGeometry其实就是获取一个List,调用OnFillVBO设置顶点数据,再调用所有的BaseVertexEffect组件进行顶点修改,最后传递给canvasRenderer。 OnFillVBO就是我们常用的设置顶点的地方,只要在里面给vbo的参数Add数据就可以了,重复一下上文说过的,Add的数目必须是4的倍数。 Image和Text都是通过这里设置顶点数据的。

上面有提到BaseVertexEffect,这个就是另外一个可以修改顶点信息的地方,它是一个修饰的组件,以Text和Outline为例,Text是一个Graphic,在控件上面添加的Outline就是一个BaseVertexEffect,Graphic在运行的时候会获取控件上面所有的BaseVertexEffect,然后设置顶点的时候依次调用。 我们可以实现一个自定义效果,继承自BaseVertexEffect,然后重载ModifyVertex函数进行顶点设置。

原文链接

你可能感兴趣的:(UGUI)