1. 程式人生 > 實用技巧 >unity探索者之UGUI圓形圖片元件

unity探索者之UGUI圓形圖片元件

版權宣告:本文為原創文章,轉載請宣告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;

        protected
override 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,記憶體會額外計算,綜合考慮下,也只能這樣了