最近工程需要用到一个多边形用来查看角色属性,于是就研究了下Mesh用网格做了一个。遗憾的的 UGUI 渲染不了 3D 物体,然后又用了一段时间研究了下UGUI的网格绘制。
不过终于还是完成了,虽然有些瑕疵…… 好吧 有很大的问题 UV 需要自己计算。(如果有朋友精通这一块,希望能帮忙改进一下)
下边是5.2以下版本使用 的
在Unity中一个Mesh使用3个顶点就能画出来,但是UGUI需要使用四个顶点才行,所以在画一些特殊模型的时候就会产生一些废点(对图形没影响但是必须存在)。
下面要开始了。额……再等等,先让我借用几张图
Ok 先上使用教
先添加个这个
程:
然后在这下边创建个空物体
然后添加这个脚本
然后就可以编辑这个脚本的属性 实现不同的多边形啦
使用polygon脚本 可以实现很多种形状 比如这些:
注意:上边这些都是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); } } }