Unity项目优化

Unity UI图片的一种优化方式

2020-10-15  本文已影响0人  塘朗山小钻风

项目中使用的不少UI图片是轴对称的,包括:

1)横轴对称或纵轴对称

2)同时满足横轴对称和纵轴对称

图1:竖轴对称图片

可以使用镜像效果来节省图片资源。第一种情况可以省下完整资源的一半,第二种情况则可以省略3/4。普通的方法则是一个Image GameObject下面挂载1个或3个Image。这些Image的scale的x或y分量值设置为-1, 就产生一个镜像了,然后开发者小心翼翼把他们对齐。这个过程太繁琐,而且产生了冗余的GameObject。

更好的办法是使用纹理采样的Wrap Mode来实现。先设置图片Wrap Mode:

图2:Wrap Mode的设置

然后上代码:

public class MirrorImage : Image

{

    [SerializeField]

    public Vector2Int m_MirrorAttr = Vector2Int.one;

    protected override void OnPopulateMesh(VertexHelper toFill)

    {

        if (type == Type.Simple)

        {

            GenerateSimpleSprite(toFill, preserveAspect);

            return;

        }

        base.OnPopulateMesh(toFill);

    }

    void GenerateSimpleSprite(VertexHelper vh, bool lPreserveAspect)

    {

        var activeSprite = overrideSprite;

        Vector4 v = GetDrawingDimensions(lPreserveAspect);

        var uv = (activeSprite != null) ? UnityEngine.Sprites.DataUtility.GetOuterUV(activeSprite) : Vector4.zero;

        uv.z *= m_MirrorAttr.x;

        uv.w *= m_MirrorAttr.y;

        var color32 = color;

        vh.Clear();

        vh.AddVert(new Vector3(v.x, v.y), color32, new Vector2(uv.x, uv.y));

        vh.AddVert(new Vector3(v.x, v.w), color32, new Vector2(uv.x, uv.w));

        vh.AddVert(new Vector3(v.z, v.w), color32, new Vector2(uv.z, uv.w));

        vh.AddVert(new Vector3(v.z, v.y), color32, new Vector2(uv.z, uv.y));

        vh.AddTriangle(0, 1, 2);

        vh.AddTriangle(2, 3, 0);

    }

    private Vector4 GetDrawingDimensions(bool shouldPreserveAspect)

    {

        var activeSprite = overrideSprite;

        var padding = activeSprite == null ? Vector4.zero : UnityEngine.Sprites.DataUtility.GetPadding(activeSprite);

        var size = activeSprite == null ? Vector2.zero : new Vector2(activeSprite.rect.width, activeSprite.rect.height);

        Rect r = GetPixelAdjustedRect();

        // Debug.Log(string.Format("r:{2}, size:{0}, padding:{1}", size, padding, r));

        int spriteW = Mathf.RoundToInt(size.x);

        int spriteH = Mathf.RoundToInt(size.y);

        var v = new Vector4(

                padding.x / spriteW,

                padding.y / spriteH,

                (spriteW - padding.z) / spriteW,

                (spriteH - padding.w) / spriteH);

        if (shouldPreserveAspect && size.sqrMagnitude > 0.0f)

        {

            var spriteRatio = size.x / size.y;

            var rectRatio = r.width / r.height;

            if (spriteRatio > rectRatio)

            {

                var oldHeight = r.height;

                r.height = r.width * (1.0f / spriteRatio);

                r.y += (oldHeight - r.height) * rectTransform.pivot.y;

            }

            else

            {

                var oldWidth = r.width;

                r.width = r.height * spriteRatio;

                r.x += (oldWidth - r.width) * rectTransform.pivot.x;

            }

        }

        v = new Vector4(

                r.x + r.width * v.x,

                r.y + r.height * v.y,

                r.x + r.width * v.z,

                r.y + r.height * v.w

                );

        return v;

    }

}

[CustomEditor(typeof(MirrorImage), true)]

[CanEditMultipleObjects]

public class MirrorImageEditor : ImageEditor

{

    public override void OnInspectorGUI()

    {

        base.OnInspectorGUI();

        var property = serializedObject.FindProperty("m_MirrorAttr");

        EditorGUILayout.PropertyField(property);

        serializedObject.ApplyModifiedProperties();

    }

}

效果如下图:

图3:最终效果

PS:如果需要的是重复模式,比如绳子的每两节完全一样的效果。Wrap Mode选择Repeat就可以。

上一篇下一篇

猜你喜欢

热点阅读