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,内存会额外计算,综合考虑下,也只能这样了

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值