Unity 2D Sprite九宫格(NineSliced)

发表于2018-04-17
评论0 1.03w浏览
Unity在2017年支持新的2D系统,有九宫格、TileMap等强大的2D特性,考虑到有些人还不熟悉,下面就和大家介绍下2D Sprite九宫格开发。




C#代码:
*Shader修改自unity5.5.0内置shader
* set Image Import Setting ->MeshType to Full Rect
*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[DisallowMultipleComponent]
[ExecuteInEditMode]
[RequireComponent(typeof(SpriteRenderer))]
public class NineSlicedProvider : MonoBehaviour {
    public bool refreshEveryFrame = false;
    SpriteRenderer m_SpriteRenderer;
    SpriteRenderer spriteRenderer {
        get{
            if (m_SpriteRenderer == null)
            {
                m_SpriteRenderer = this.GetComponent<SpriteRenderer> ();
            }
            return m_SpriteRenderer;
        }
    }
    Material m_Material;
    Material material
    {
        get{
            if (spriteRenderer == null)
            {
                m_Material = null;
                return null;
            }
            if (m_Material == null)
            {
                spriteRenderer.sharedMaterial = new Material(Shader.Find("Rickshao/NineSlicedShader"));
                m_Material = spriteRenderer.sharedMaterial;
            }
            return m_Material;
        }
    }
    void OnEnable()
    {
        SetShaderVaries ();
    }
    // Update is called once per frame
    void Update () {
        if (refreshEveryFrame)
        {
            SetShaderVaries();
        }
    }
    void SetShaderVaries()
    {
        if (spriteRenderer == null || spriteRenderer.sprite == null)
            return;
        float width = spriteRenderer.sprite.rect.width;
        float height = spriteRenderer.sprite.rect.height;
        float borderLeft = spriteRenderer.sprite.border.x;
        float borderBottom = spriteRenderer.sprite.border.y;
        float borderRight = spriteRenderer.sprite.border.z;
        float borderTop = spriteRenderer.sprite.border.w;
        float left = borderLeft / width;
        float bottom = borderBottom / height;
        float right = borderRight / width;
        float top = borderTop / height;
        //Debug.Log ("top " + top + " bottom " + bottom + " left " + left + " right " + right);
        material.SetFloat("top", top);
        material.SetFloat("bottom", bottom);
        material.SetFloat("right", right);
        material.SetFloat("left", left);
        material.SetFloat("sx", this.transform.localScale.x);
        material.SetFloat ("sy", this.transform.localScale.y);
    }
}

Shader代码:
*Shader修改自unity5.5.0内置shader
* set Image Import Setting ->MeshType to Full Rect
*/
Shader "Rickshao/NineSlicedShader"
{
    Properties
    {
        [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {}
        [HideInInspector]_Color ("Tint", Color) = (1,1,1,1)
        [HideInInspector][MaterialToggle] PixelSnap ("Pixel snap", Float) = 0
    }
    SubShader
    {
        Tags
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }
        Cull Off
        Lighting Off
        ZWrite Off
        Blend One OneMinusSrcAlpha
        Pass
        {
        CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma target 2.0
            #pragma multi_compile _ PIXELSNAP_ON
            #pragma multi_compile _ ETC1_EXTERNAL_ALPHA
            #include "UnityCG.cginc"
            float top;
            float bottom;
            float left;
            float right;
            float sx;
            float sy;
            struct appdata_t
            {
                float4 vertex   : POSITION;
                float4 color    : COLOR;
                float2 texcoord : TEXCOORD0;
                //UNITY_VERTEX_INPUT_INSTANCE_ID //copied from 5.5, not work in 5.4
            };
            struct v2f
            {
                float4 vertex   : SV_POSITION;
                fixed4 color    : COLOR;
                float2 texcoord  : TEXCOORD0;
                //UNITY_VERTEX_OUTPUT_STEREO
            };
            fixed4 _Color;
            float2 UVTransform(float2 origin)
            {
                float2 result = origin;
                if(left + right > sx)
                {
                    result.x = origin.x;
                }
                else
                {
                    if (origin.x * sx < left)
                    {
                        result.x = origin.x * sx;
                    }
                    else
                    {
                        if ((1 - origin.x) * sx < right)
                        {
                            result.x = 1 - (1 - origin.x) * sx;
                        }
                        else
                        {
                            result.x = (origin.x * sx - left) / (sx - left - right)*(1 - left - right) + left;
                        }
                    }
                }
                if (top + bottom > sy)
                {
                    result.y = origin.y;
                }else
                {
                    if (origin.y * sy < top)
                    {
                        result.y = origin.y * sy;
                    }
                    else
                    {
                        if ((1 - origin.y) * sy < bottom)
                        {
                            result.y = 1 - (1 - origin.y) * sy;
                        }
                        else
                        {
                            result.y = (origin.y * sy - top) / (sy - top - bottom)*(1 - top - bottom) + top;
                        }
                    }
                }
                return result;
            }
            v2f vert(appdata_t IN)
            {
                v2f OUT;
                UNITY_SETUP_INSTANCE_ID(IN);
                UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT);
                OUT.vertex = UnityObjectToClipPos(IN.vertex);
                OUT.texcoord = IN.texcoord;
                OUT.color = IN.color * _Color;
                #ifdef PIXELSNAP_ON
                OUT.vertex = UnityPixelSnap (OUT.vertex);
                #endif
                return OUT;
            }
            sampler2D _MainTex;
            sampler2D _AlphaTex;
            fixed4 SampleSpriteTexture (float2 uv)
            {
                fixed4 color = tex2D (_MainTex, uv);
#if ETC1_EXTERNAL_ALPHA
                // get the color from an external texture (usecase: Alpha support for ETC1 on android)
                color.a = tex2D (_AlphaTex, uv).r;
#endif //ETC1_EXTERNAL_ALPHA
                return color;
            }
            fixed4 frag(v2f IN) : SV_Target
            {
                fixed4 c = SampleSpriteTexture (UVTransform(IN.texcoord)) * IN.color;
                c.rgb *= c.a;
                return c;
            }
        ENDCG
        }
    }
}
来自:https://blog.csdn.net/rickshaozhiheng/article/details/53608168

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引