UGUI Image适配

UGUI Image适配

如果在Image中放入一个图片,但是Image的长宽比和sprite的长宽比不一样,就会出现拉伸现象。

正常图片

在这里插入图片描述

长宽比不一样时

在这里插入图片描述

所以做了一个工具来适配,有两种适配模式

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如果用两种布局方式,同样生效

布局1

在这里插入图片描述

布局2

在这里插入图片描述

shader

// A code block
Shader "UI/Image"
{
    Properties
    {
        _MainTex ("Sprite Texture", 2D) = "white" {}
        _Color ("Tint", Color) = (1,1,1,1)

        _StencilComp ("Stencil Comparison", Float) = 8
        _Stencil ("Stencil ID", Float) = 0
        _StencilOp ("Stencil Operation", Float) = 0
        _StencilWriteMask ("Stencil Write Mask", Float) = 255
        _StencilReadMask ("Stencil Read Mask", Float) = 255

        _ColorMask ("Color Mask", Float) = 15

        [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
    }

    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }

        Stencil
        {
            Ref [_Stencil]
            Comp [_StencilComp]
            Pass [_StencilOp]
            ReadMask [_StencilReadMask]
            WriteMask [_StencilWriteMask]
        }

        Cull Off
        Lighting Off
        ZWrite Off
        ZTest [unity_GUIZTestMode]
        Blend SrcAlpha OneMinusSrcAlpha
        ColorMask [_ColorMask]

        Pass
        {
            Name "Default"
        CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 2.0

            #include "UnityCG.cginc"
            #include "UnityUI.cginc"

            #pragma multi_compile_local _ UNITY_UI_CLIP_RECT
            #pragma multi_compile_local _ UNITY_UI_ALPHACLIP

            struct appdata_t
            {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
                UNITY_VERTEX_INPUT_INSTANCE_ID
            };

            struct v2f
            {
                float4 vertex   : SV_POSITION;
                fixed4 color    : COLOR;
                float2 texcoord  : TEXCOORD0;
                float4 worldPosition : TEXCOORD1;
                UNITY_VERTEX_OUTPUT_STEREO
            };

            sampler2D _MainTex;
            fixed4 _Color;
            fixed4 _TextureSampleAdd;
            float4 _ClipRect;
            float4 _MainTex_ST;

            v2f vert(appdata_t v)
            {
                v2f OUT;
                UNITY_SETUP_INSTANCE_ID(v);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
                OUT.worldPosition = v.vertex;
                OUT.vertex = UnityObjectToClipPos(OUT.worldPosition);

                OUT.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex);

                OUT.color = v.color * _Color;
                return OUT;
            }

            fixed4 frag(v2f IN) : SV_Target
            {
                half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;

                #ifdef UNITY_UI_CLIP_RECT
                color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect);
                #endif

                #ifdef UNITY_UI_ALPHACLIP
                clip (color.a - 0.001);
                #endif

                return color;
            }
        ENDCG
        }
    }
}

C#

// A code block
namespace Game.UI
{
    public enum AdapterType
    {
        Max,
        Min,
    }
}
using System;
using Unity.Mathematics;
#if UNITY_EDITOR
using UnityEditor;  
#endif

using UnityEngine;
using UnityEngine.UI;

namespace Game.UI
{
    [ExecuteInEditMode]
    public class ImageAdapter : MonoBehaviour
    {
        public AdapterType AdapterType = AdapterType.Max;

        public void Refresh()
        {
            var img = GetComponent<Image>();
            var m_Material = img.material;
            var tf = transform as RectTransform;

            float2 w_h;
            if (Mathf.Abs(tf.anchorMin.x - tf.anchorMax.x) < 0.001f)
                w_h.x = tf.sizeDelta.x;
            else
                w_h.x = tf.rect.width;
            
            if (Mathf.Abs(tf.anchorMin.y - tf.anchorMax.y)< 0.001f)
                w_h.y = tf.sizeDelta.y;
            else
                w_h.y = tf.rect.height;
            float curRatio = w_h.y / w_h.x;
            float spRatio = img.sprite.rect.height / img.sprite.rect.width;

            Vector4 offset;
            offset.x = 1;
            offset.y = 1;
            offset.z = 0;
            offset.w = 0;
            
            switch (AdapterType)
            {
                case AdapterType.Max:
                    if (curRatio <= spRatio)
                    {
                        offset.y = curRatio / spRatio;
                        offset.w = 0.5f - 0.5f * offset.y;
                    }
                    else
                    {
                        offset.x = spRatio / curRatio;
                        offset.z = 0.5f - 0.5f * offset.x;
                    }
                    break;
                case AdapterType.Min:
                    if (curRatio <= spRatio)
                    {
                        offset.x = spRatio / curRatio;
                        offset.z = 0.5f - 0.5f * offset.x;
                    }
                    else
                    {
                        offset.y = curRatio / spRatio;
                        offset.w = 0.5f - 0.5f * offset.y;
                    }
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }
            m_Material.SetVector("_MainTex_ST" ,offset);
        }
    }
    
#if UNITY_EDITOR    
    [CustomEditor(typeof(ImageAdapter))]
    [CanEditMultipleObjects]
    public class MyPlayerEditor : Editor
    {
 
        public override void OnInspectorGUI()
        {
            base.OnInspectorGUI();
            if(GUILayout.Button("刷新")) {
                ((ImageAdapter)target).Refresh();
            }
        }
    }
#endif
}

猜你喜欢

转载自blog.csdn.net/qq_41041725/article/details/127534463