Unity 绘制多边形

时间:2022-06-26 03:59:42

  最近工程需要用到一个多边形用来查看角色属性,于是就研究了下Mesh用网格做了一个。遗憾的的 UGUI 渲染不了 3D 物体,然后又用了一段时间研究了下UGUI的网格绘制。

不过终于还是完成了,虽然有些瑕疵…… 好吧 有很大的问题 UV 需要自己计算。(如果有朋友精通这一块,希望能帮忙改进一下)

下边是5.2以下版本使用 的

5.2(包括)以上的 请点击这个连接 

 在Unity中一个Mesh使用3个顶点就能画出来,但是UGUI需要使用四个顶点才行,所以在画一些特殊模型的时候就会产生一些废点(对图形没影响但是必须存在)。

下面要开始了。额……再等等,先让我借用几张图

Ok 先上使用教

先添加个这个

Unity 绘制多边形

然后在这下边创建个空物体

Unity 绘制多边形

然后添加这个脚本

Unity 绘制多边形

然后就可以编辑这个脚本的属性 实现不同的多边形啦

Unity 绘制多边形

使用polygon脚本 可以实现很多种形状 比如这些:

 

Unity 绘制多边形

Unity 绘制多边形

Unity 绘制多边形

Unity 绘制多边形

 

Unity 绘制多边形

Unity 绘制多边形

Unity 绘制多边形

 

注意:上边这些都是UGUI,并不是模型网格;

5.2的UGUIAPI改动比较大所以不能想想兼容,我是在原作者的代码基础上改的。(希望原作者不会介意……额 我还是发个邮件说一下吧!!!!!!)

使用步骤和上边一样,这两个具有相同的问题就是UV的贴的时候没有贴好(原谅我这个数学渣渣),在原基础上增加了顶点网格的设置,其余的没有更改。

 5.2(包涵)以上版本的 在上边的连接可以下载到 ,下边是5.2以下版本的。

 

//*********************************************************************
//
//                       ScriptName     : UIPolygonPast
//                          
//                              筱程       
//                                   
//*********************************************************************

using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
public class UIPolygonPast : MaskableGraphic
{

    List<Vector2> pointPosition = new List<Vector2>();
    List<Vector2> Vertex = new List<Vector2>();
    List<Vector2> UV     = new List<Vector2>();
    // 是否使用顶点画  默认是不使用
    // 使用需要用户自己传入顶点位置 
    // 否则会根据顶点数目 以零点位置自动计算圆形顶点位置
    [SerializeField]
    Texture m_Textrue;

    public bool usingVertex;

    // 是否中空
    public bool fill = true;

    // 顶点数目
    [Range(3, 360)]
    public int sides = 3;
    // 选择角度
    [Range(0, 360)]
    public float Rotation = 90;
    // 边缘厚度
    [Range(0, 500)]
    public float Thickness = 5;
    // 顶点距离
    [Range(0, 1)]
    public float[] VerticesDistances = new float[3];

    private float size = 1f;
    public override Texture mainTexture {
        get {
            return m_Textrue == null ? s_WhiteTexture : m_Textrue;
        }
    }
    public Texture texture {
        get {
            return m_Textrue;
        }
        set {
            if (m_Textrue == value)
                return;
            m_Textrue = value;
            SetVerticesDirty();
            SetMaterialDirty();
        }
    }
    /// <summary>
    /// 设置图片顶点
    /// </summary>
    /// <param name="_Vertex"></param>
    public void DrwaPolyonVertex(List<Vector2> _Vertex) {
        DrwaPolyonVertex(_Vertex, null);
    }
    /// <summary>
    ///  设置图片顶点
    /// </summary>
    /// <param name="_Vertex">顶点</param>
    /// /// <param name="_UV">UI</param>
    public void DrwaPolyonVertex(List<Vector2> _Vertex,List<Vector2> _UV) {
        Vertex      = _Vertex;
        UV          = _UV;
        usingVertex = true;
    }
    /// <summary>
    /// 设置顶点数目
    /// </summary>
    /// <param name="_sides"></param>
    public void DrwaPolygon(int _sides) {
        DrwaPolygon(_sides, null);
    }
    /// <summary>
    /// 设置顶点数目
    /// </summary>
    /// <param name="_sides"></param>
    /// <param name="_VerticesDistances">顶点距离信息</param>
    public void DrwaPolygon(int _sides, float[] _VerticesDistances) {
        DrwaPolygon(_sides, _VerticesDistances, 90);
    }
    /// <summary>
    /// 设置顶点数目
    /// </summary>
    /// <param name="_sides"></param>
    /// <param name="_VerTicesDstances">顶点距离信息</param>
    /// <param name="_Rotation">顶点旋转</param>
    public void DrwaPolygon(int _sides, float[] _VerTicesDstances,float _Rotation) {
        sides = _sides;
        if (_VerTicesDstances != null)
        VerticesDistances = _VerTicesDstances;
        Rotation = _Rotation;
        usingVertex = false;
    }
    private Vector2 CalculatedPosition(Vector2 p1, Vector2 p2, Rect rect) {
        p1.x *= rect.width;
        p1.y *= rect.height;
        return p1;
    }

    // UI网格都是四边形,所以需要四个顶点
    // 但是我们只需要三个顶点,所以就需要添加一个废点
    // 否则不能组成网格
    // 最后所有点数的总和应该是4的倍数
    protected override void OnFillVBO(List<UIVertex> vbo) {
        vbo.Clear();

        if (usingVertex) {
            VerterxDrwa(ref vbo);
        } else {
            VerterxNumberDrwa(ref vbo);
        }
    }
    // 用顶点画
    private void VerterxDrwa(ref List<UIVertex> vbo) {
        Vector2 pos1 = Vector2.zero;
        Vector2 pos2 = Vector2.zero;
        Vector2 pos3 = Vector2.zero;
        Vector2 pos4 = Vector2.zero;
        if (Vertex.Count == 0) {
            pointPosition.Clear();
            pointPosition.Add(new Vector2(0, -1) / 2f);
            pointPosition.Add(new Vector2(-1, -0.5f) / 2f);

            pointPosition.Add(new Vector2(-1, 0.5f) / 2f);
            pointPosition.Add(new Vector2(0, 1) / 2f);
            pointPosition.Add(new Vector2(1, 0.5f) / 2f);
            pointPosition.Add(new Vector2(1, -0.5f) / 2f);
        } else {
            pointPosition.Clear();
            pointPosition = Vertex;
        }

        for (int i = 0; i < pointPosition.Count; i++) {
            Vector2 pos      = pointPosition[i];
            pointPosition[i] = CalculatedPosition(pos, rectTransform.pivot, rectTransform.rect);
        }
        int count   = pointPosition.Count;
        Vector2 uv1 = new Vector2(0, 0);
        Vector2 uv2 = new Vector2(0, 1);
        Vector2 uv3 = new Vector2(1, 1);
        Vector2 uv4 = new Vector2(1, 0);
        for (int i  = 0; i < count - 1; i++) {

            pos1 = pointPosition[i];
            pos2 = pointPosition[i] + ( pointPosition[i] - Vector2.zero ) * -0.2f;
            pos3 = Vector2.zero;
            pos4 = pointPosition[i + 1];
            if (UV != null && count==UV.Count) {
                uv3 = new Vector2(0.5f, 0.5f);
                uv1 = UV[i];
                uv4 = UV[i + 1];
                uv2 = uv1 + ( uv1 - uv3 ) * -0.2f;
            }
            AddUIVerterx(ref vbo, new Vector2[] { pos1, pos2, pos3, pos4 }, new Vector2[] { uv1, uv2, uv3, uv4 });
        }

        pos1 = pointPosition[count - 1];
        pos2 = pointPosition[count - 1] + ( pointPosition[count - 1] - Vector2.zero ) * -0.2f;
        pos3 = Vector2.zero;
        pos4 = pointPosition[0];
        if (UV != null && count == UV.Count) {
            uv1 = UV[count - 1];
            uv4 = UV[0];
            uv2 = uv1 + ( uv1 - uv3 ) * -0.2f;
        }
        AddUIVerterx(ref vbo, new Vector2[] { pos1, pos2, pos3, pos4 }, new Vector2[] { uv1, uv2, uv3, uv4 });
    }
    //  用顶点数画多边形
    private void VerterxNumberDrwa(ref List<UIVertex> vbo) {

        float degrees = 360f / sides;

         size = rectTransform.rect.width > rectTransform.rect.height ? rectTransform.rect.height : rectTransform.rect.width;
        Thickness = Mathf.Clamp(Thickness, 0, size / 2);

        if (VerticesDistances == null || VerticesDistances.Length != sides + 1) {
            VerticesDistances = new float[sides + 1];
            for (int i = 0; i < sides; i++)
                VerticesDistances[i] = 1;
        }
        VerticesDistances[sides] = VerticesDistances[0];
        Vector2 pos1 ;
        Vector2 pos2 ;
        Vector2 pos3 ;
        Vector2 pos4 ;
        Vector2 lastPosx = Vector2.zero;
        Vector2 lastPosy = Vector2.zero;
        Vector2 uv1 = new Vector2(0, 0);
        Vector2 uv2 = new Vector2(0, 1);
        Vector2 uv3 = new Vector2(1, 1);
        Vector2 uv4 = new Vector2(1, 0);
        //Vector2 lastuv = new Vector2(0.5f, 0.5f);
        for (int i  = 0; i <= sides; i++) {

            float outer = -rectTransform.pivot.x * size * VerticesDistances[i];
            float inner = -rectTransform.pivot.x * size * VerticesDistances[i] + Thickness;
            float rad   = Mathf.Deg2Rad * ( i * degrees + Rotation );
            float c     = Mathf.Cos(rad);
            float s     = Mathf.Sin(rad);
            pos1        = lastPosx;
            pos2        = new Vector2(outer * c, outer * s);

            if (fill) {
                pos3 = Vector2.zero;
                pos4 = Vector2.zero;
            } else {
                pos3 = new Vector2(inner * c, inner * s);
                pos4 = lastPosy;
            }
            #region
            //int x = (int) (pos1.x < 0 ? pos1.x * -1 : pos1.x * 2);
            //int y = (int)( pos1.y < 0 ? pos1.y * -1 : pos1.y * 2 );

            //float uvx = 0;
            //float uvy = 0;
            //    if (x != 0) {
            //        uvx =x / size;
            //    }
            //    if (y != 0) {
            //        uvy =y / size;
            //    }
          
            //uv2 = new Vector2(uvx, uvy);  
            //uv1 = lastuv;    
            //lastuv = uv2;
            #endregion
            lastPosx = pos2;
            lastPosy = pos3;
            AddUIVerterx(ref vbo, new Vector2[] { pos1, pos2, pos3, pos4 }, new Vector2[] { uv1, uv2, uv3, uv4 });
        }
    }
    private void AddUIVerterx(ref List<UIVertex> vbo, Vector2[] pos, Vector2[] uv = null) {
        UIVertex vert = UIVertex.simpleVert;
        for (int i = 0; i < pos.Length; i++) {
            vert.position = pos[i];
            vert.color = color;
            if (uv != null && uv.Length == pos.Length)
                vert.uv0 = uv[i];
            vbo.Add(vert);
        }
    }
}