多边形裁剪图片

发布时间 2023-07-25 23:23:48作者: yanghui01

效果

 

using UnityEngine;
using UnityEngine.Sprites;
using UnityEngine.UI;

[RequireComponent(typeof(Image))]
public class PolygonMeshEffect : BaseMeshEffect
{

    [SerializeField]
    [Range(3, 60)]
    private int m_SegmentCount = 3;

    public int segmentCount { get { return m_SegmentCount; } }

    private Image m_Image;

    public Image image
    {
        get
        {
            if (null == m_Image)
                m_Image = GetComponent<Image>();
            return m_Image;
        }
    }

    public override void ModifyMesh(VertexHelper vh)
    {
        if (!enabled) return;
        if (null == image) return;
        if (image.type != Image.Type.Simple) return;

        var sp = image.sprite;
        var color = image.color;

        vh.Clear();

        var imageRect = image.GetPixelAdjustedRect(); //左下角为pivot的坐标
        var vertCenter = new Vector3(imageRect.x + imageRect.width * 0.5f, imageRect.y + imageRect.height * 0.5f);

        float radius = (imageRect.width > imageRect.height) ? imageRect.height * 0.5f : imageRect.width * 0.5f; //使用短的边作为半径
        var uv = (null != sp) ? DataUtility.GetOuterUV(sp) : Vector4.zero;
        var uvCenter = new Vector2((uv.x + uv.z) * 0.5f, (uv.y + uv.w) * 0.5f);

        float sx = (uv.z - uv.x) / imageRect.width;
        float sy = (uv.w - uv.y) / imageRect.height;

        float radianPerSegment = 2 * Mathf.PI / m_SegmentCount;

        vh.AddVert(vertCenter, color, uvCenter);

        Vector3 tempVert = vertCenter;
        Vector2 tempUv = uvCenter;
        float tempRadian = 0;
        for (int i = 0; i < m_SegmentCount; ++i)
        {
            float dx = Mathf.Cos(tempRadian) * radius;
            float dy = Mathf.Sin(tempRadian) * radius;

            tempVert.x = vertCenter.x + dx;
            tempVert.y = vertCenter.y + dy;

            tempUv.x = uvCenter.x + dx * sx;
            tempUv.y = uvCenter.y + dy * sy;

            vh.AddVert(tempVert, color, tempUv);
            tempRadian += radianPerSegment;
        }

        for (int i = 1; i < m_SegmentCount; ++i)
        {
            vh.AddTriangle(0, i + 1, i); //顺时针, SceneView的wireframe才能正确显示
        }
        vh.AddTriangle(0, 1, m_SegmentCount); //首尾相连
    }

}

 

参考

[Unity UGUI] 制作圆形图片的两种方式 - 知乎 (zhihu.com)