unity探索者之UGUI圓形圖片元件
阿新 • • 發佈:2020-08-18
版權宣告:本文為原創文章,轉載請宣告https://www.cnblogs.com/unityExplorer/p/13524824.html
使用UGUI進行遊戲開發的過程中經常會遇到一個問題:玩家的頭像在不同的介面或場景顯示的形狀可能不一樣,有的地方需要顯示成圓形,有些地方需要顯示成方形
為了避免這種問題,我們選擇毆打策劃,恩。。。但是如果打策劃打不過,美術小姐姐又不好意思打的話,怎麼辦?真出兩套圖,那不是一個精益求精的攻城獅樂意的看到的結果
有沒有辦法可以讓同一張圖可以顯示成不同的形狀呢?有的朋友說了,可以用UGUI的Mask來實現
這也是一種辦法,但是這種辦法有個弊端,就是遮罩圖片尺寸很小的話,邊緣鋸齒會相當嚴重,這與UGUI中Mask的原理有關
所以有沒有更好的辦法呢?有的,我們先分析下UGUI圖片的渲染原理
實際上,UGUI中的圖片其實就是一個由兩個三角面拼接成的平面模型
當場景中只有一張圖片時,可以看到,Tris是2,Verts是4
基於此,將頂點圍成的圖形修改成圓形,那就實現了我們的目的
將n個三角形拼接到一起就是一個近似圓形的形狀,比如:
實現程式碼如下:
public class CircleImage : Image { public int segements = 40; public float fillPercent = 1; protectedoverride void OnPopulateMesh(VertexHelper vh) { vh.Clear(); float tw = rectTransform.rect.width; float th = rectTransform.rect.height; float outerRadius = 0.5f * Mathf.Min(tw, th); float degreeDelta = 2 * Mathf.PI / segements;int curSegements = (int)(segements * fillPercent);
//因UGUI的錨點系統,這裡需要考慮pivot的差值,以避免因物體原點的改變導致圖片歪了 Vector2 pivotVector = new Vector2(tw * (0.5f - rectTransform.pivot.x), th * (0.5f - rectTransform.pivot.y)); Vector4 uv = overrideSprite != null ? DataUtility.GetOuterUV(overrideSprite) : Vector4.zero; Vector2 center = new Vector2(uv.x + uv.z, uv.y + uv.w) * 0.5f; float uvScaleX = (uv.z - uv.x) / tw; float uvScaleY = (uv.w - uv.y) / th; float curDegree = 0; UIVertex uiVertex; int verticeCount; int triangleCount; Vector2 curVertice; curVertice = Vector2.zero; verticeCount = curSegements + 1; uiVertex = new UIVertex { color = color, position = curVertice + pivotVector, uv0 = new Vector2(curVertice.x * uvScaleX, curVertice.y * uvScaleY) + center }; vh.AddVert(uiVertex); for (int i = 1; i < verticeCount; i++) { curVertice = new Vector2(Mathf.Cos(curDegree) * outerRadius, Mathf.Sin(curDegree) * outerRadius); curDegree += degreeDelta; uiVertex = new UIVertex { color = color, position = curVertice + pivotVector, uv0 = new Vector2(curVertice.x * uvScaleX, curVertice.y * uvScaleY) + center }; vh.AddVert(uiVertex); } triangleCount = curSegements * 3; for (int i = 0, vIdx = 1; i < triangleCount - 3; i += 3, vIdx++) { vh.AddTriangle(vIdx, 0, vIdx + 1); } if (fillPercent == 1) { //首尾頂點相連 vh.AddTriangle(verticeCount - 1, 0, 1); } } }
將正中心的點作為圖形頂點的起始點,按照逆時針或順時針方向畫三角形,最終再回到中心點,就形成了一個封閉的圓形
三角面的數量決定了圓形的圓滑程度,作為元件,我們可以將三角面的數量作為引數對外暴露
這個元件繼承自UGUI的Image,所以也擁有Image的部分屬性,事實上出於效能開銷考慮,繼承RawImage價效比會更高
但是RawImage有個一個問題,就是不相容圖集系統,也就是說,即使是打在圖集中的圖片,如果使用RawImage,記憶體會額外計算,綜合考慮下,也只能這樣了