这个是参考大神的修改了一下渲染方式实现的,可以去查看原帖的,原贴是圆形头像,原理讲的非常详细
我写的这个只支持正方形图片,效果是酱紫的~
一共三个代码,还需要两个代码,原帖里都有的,我只是修改了其中一个。
1 using System.Collections.Generic; 2 using UnityEngine; 3 using UnityEngine.UI; 4 using UnityEngine.Sprites; 5 6 [AddComponentMenu("UI/Circle Image")] 7 public class CircleImage1 : BaseImage { 8 // Use this for initialization 9 void Awake () { 10 innerVertices = new List<Vector3>(); 11 outterVertices = new List<Vector3>(); 12 } 13 14 // Update is called once per frame 15 void Update () { 16 17 } 18 19 20 [Range(0, 1)] 21 public float scale = 1f; 22 23 [Range(2, 30)] 24 public int segements = 2; 25 26 private List<Vector3> innerVertices; 27 private List<Vector3> outterVertices; 28 29 protected override void OnPopulateMesh(VertexHelper vh) 30 { vh.Clear(); 31 Rect pixelAdjustedRect = this.GetPixelAdjustedRect(); 32 33 Vector4 uv = overrideSprite != null ? DataUtility.GetOuterUV(overrideSprite) : Vector4.zero; 34 //Debug.LogError("uv:" + uv+","+uv.w+","+uv.x+","+uv.y+","+uv.z); 35 36 Vector2 u = new Vector2(0, 0); 37 float w = pixelAdjustedRect.width; 38 39 #region 40 //1 41 for (int i =0; i < segements+1; i++) 42 { 43 UIVertex uivertex = new UIVertex(); 44 uivertex.color = color; 45 if (i ==0) 46 { 47 //半径* 48 uivertex.uv0 = new Vector2(uv.x + (scale / 2) * (uv.z - uv.x) * (1 - Mathf.Sin(i * 90 / segements)), uv.y + (scale / 2) * (uv.w - uv.y) * (1 - Mathf.Cos(i * 90 / segements))); 49 u = new Vector2((scale / 2) * (1 - Mathf.Sin(i * 90 / segements)),(scale / 2) * (1 - Mathf.Cos(i * 90 / segements))); 50 } 51 else 52 { 53 uivertex.uv0 = new Vector2(uv.x + (scale / 2) * (uv.z - uv.x) * (1 - Mathf.Sin(Mathf.PI / (180f / (i * 90 / segements)))), uv.y + (scale / 2) * (uv.w - uv.y) * (1 - Mathf.Cos(Mathf.PI / (180f / (i * 90 / segements))))); 54 u = new Vector2((scale / 2) * (1 - Mathf.Sin(Mathf.PI / (180f / (i * 90 / segements)))),(scale / 2) * (1 - Mathf.Cos(Mathf.PI / (180f / (i * 90 / segements))))); 55 } 56 uivertex.position = new Vector3(w * u.x - w / 2, w * u.y - w / 2); 57 58 vh.AddVert(uivertex); 59 } 60 //2 61 for (int i = 0; i < segements + 1; i++) 62 { 63 UIVertex uivertex = new UIVertex(); 64 uivertex.color = color; 65 if (i == 0) 66 { 67 uivertex.uv0 = new Vector2(uv.x + (uv.z - uv.x) * (scale / 2) * (1 - Mathf.Cos(i * 90 / segements)), uv.y + (uv.w - uv.y) * ((1 - scale / 2) + (scale / 2) * Mathf.Sin(i * 90 / segements))); 68 u = new Vector2((scale / 2) - (scale / 2) * Mathf.Cos(i * 90 / segements), (1 - scale / 2) + (scale / 2) * Mathf.Sin(i * 90 / segements)); 69 } 70 else 71 { 72 uivertex.uv0 = new Vector2(uv.x + (uv.z - uv.x) * (scale / 2) * (1 - Mathf.Cos(Mathf.PI / (180f / (i * 90 / segements)))), uv.y + (uv.w - uv.y) * ((1 - scale / 2) + (scale / 2) * Mathf.Sin(Mathf.PI / (180f / (i * 90 / segements))))); 73 u = new Vector2( (scale / 2) * (1 - Mathf.Cos(Mathf.PI / (180f / (i * 90 / segements)))), (1 - scale / 2) + (scale / 2) * Mathf.Sin(Mathf.PI / (180f / (i * 90 / segements)))); 74 } 75 uivertex.position = new Vector3(w * u.x - w / 2, w * u.y - w / 2); 76 vh.AddVert(uivertex); 77 } 78 //3 79 for (int i = 0; i < segements + 1; i++) 80 { 81 UIVertex uivertex = new UIVertex(); 82 uivertex.color = color; 83 if (i == 0) 84 { 85 uivertex.uv0 = new Vector2(uv.x + (uv.z - uv.x) * ((1 - scale / 2) + (scale / 2) * Mathf.Sin(i * 90 / segements)), uv.y + (uv.w - uv.y) * ((1 - scale / 2) + (scale / 2) * Mathf.Cos(i * 90 / segements))); 86 u = new Vector2((1 - scale / 2) + (scale / 2) * Mathf.Sin(i * 90 / segements), (1 - scale / 2) + (scale / 2) * Mathf.Cos(i * 90 / segements)); 87 } 88 else 89 { 90 uivertex.uv0 = new Vector2(uv.x + (uv.z - uv.x) * ((1 - scale / 2) + (scale / 2) * Mathf.Sin(Mathf.PI / (180f / (i * 90 / segements)))), uv.y + (uv.w - uv.y) * ((1 - scale / 2) + (scale / 2) * Mathf.Cos(Mathf.PI / (180f / (i * 90 / segements))))); 91 u= new Vector2((1 - scale / 2) + (scale / 2) * Mathf.Sin(Mathf.PI / (180f / (i * 90 / segements))), (1 - scale / 2) + (scale / 2) * Mathf.Cos(Mathf.PI / (180f / (i * 90 / segements)))); 92 } 93 uivertex.position = new Vector3(w * u.x - w / 2, w * u.y - w / 2); 94 vh.AddVert(uivertex); 95 } 96 //4 97 for (int i = 0; i < segements + 1; i++) 98 { 99 UIVertex uivertex = new UIVertex(); 100 uivertex.color = color; 101 if (i == 0) 102 { 103 uivertex.uv0 = new Vector2(uv.x + (uv.z - uv.x) * ((1 - scale / 2) + (scale / 2) * Mathf.Cos(i * 90 / segements)), uv.y + (uv.w - uv.y) * ((scale / 2) - (scale / 2) * Mathf.Sin(i * 90 / segements))); 104 u = new Vector2((1 - scale / 2) + (scale / 2) * Mathf.Cos(i * 90 / segements), (scale / 2) - (scale / 2) * Mathf.Sin(i * 90 / segements)); 105 } 106 else 107 { 108 uivertex.uv0 = new Vector2(uv.x + (uv.z - uv.x) * ((1 - scale / 2) + (scale / 2) * Mathf.Cos(Mathf.PI / (180f / (i * 90 / segements)))), uv.y + (uv.w - uv.y) * ((scale / 2) - (scale / 2) * Mathf.Sin(Mathf.PI / (180f / (i * 90 / segements))))); 109 u = new Vector2((1 - scale / 2) + (scale / 2) * Mathf.Cos(Mathf.PI / (180f / (i * 90 / segements))), (scale / 2) - (scale / 2) * Mathf.Sin(Mathf.PI / (180f / (i * 90 / segements)))); 110 } 111 uivertex.position = new Vector3(w * u.x - w / 2, w * u.y - w / 2); 112 vh.AddVert(uivertex); 113 } 114 115 //((点*4+8个点-3)条弦+1)个三角形 116 for (int i = 0; i < ((segements - 1) * 4 + 8 - 3 + 1); i++) 117 { 118 vh.AddTriangle(0, i + 1, i + 2); 119 } 120 #endregion 121 } 122 123 public override bool IsRaycastLocationValid(Vector2 screenPoint, Camera eventCamera) 124 { 125 // Sprite sprite = overrideSprite; 126 // if (sprite == null) 127 // return true; 128 129 130 // Debug.LogError("鼠标点击:" + screenPoint); 131 132 133 // Vector2 local; 134 // RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTransform, screenPoint, eventCamera, out local); 135 return true; 136 } 137 138 private bool Contains(Vector2 p, List<Vector3> outterVertices, List<Vector3> innerVertices) 139 { 140 var crossNumber = 0; 141 RayCrossing(p, innerVertices, ref crossNumber);//检测内环 142 RayCrossing(p, outterVertices, ref crossNumber);//检测外环 143 return (crossNumber & 1) == 1; 144 } 145 146 /// <summary> 147 /// 使用RayCrossing算法判断点击点是否在封闭多边形里 148 /// </summary> 149 /// <param name="p"></param> 150 /// <param name="vertices"></param> 151 /// <param name="crossNumber"></param> 152 private void RayCrossing(Vector2 p, List<Vector3> vertices, ref int crossNumber) 153 { 154 for (int i = 0, count = vertices.Count; i < count; i++) 155 { 156 var v1 = vertices[i]; 157 var v2 = vertices[(i + 1) % count]; 158 159 //点击点水平线必须与两顶点线段相交 160 if (((v1.y <= p.y) && (v2.y > p.y)) 161 || ((v1.y > p.y) && (v2.y <= p.y))) 162 { 163 //只考虑点击点右侧方向,点击点水平线与线段相交,且交点x > 点击点x,则crossNumber+1 164 if (p.x < v1.x + (p.y - v1.y) / (v2.y - v1.y) * (v2.x - v1.x)) 165 { 166 crossNumber += 1; 167 } 168 } 169 } 170 } 171 172 }