【Unity】2D Sprite九宫格(NineSliced)

支持新的2D系统的Unity会在2017年发布,届时会发布九宫格,TileMap等强大的2D特性,不过现在能用的只是alpha版而已,很多功能做得还不够好,接口也不完善,实际开发也比较鸡肋,所以自己写了一个2D九宫格,具体逻辑什么的有空再写
《【Unity】2D Sprite九宫格(NineSliced)》

《【Unity】2D Sprite九宫格(NineSliced)》

《【Unity】2D Sprite九宫格(NineSliced)》

C#代码:

/* *Author: 邵志恒 *Blog: http://blog.csdn.net/rickshaozhiheng/article/details/53608168 *Email: zhiheng.rick@gmail.com *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);
        // TODO 初始化的时候运用PropertyToID
        // 以后每次传int型的ID,效率更高
        // 当值没有变化的时候,不需要每一帧再传,调用一个什么东西,忘了。。。
        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代码:

/* *Author: 邵志恒 *Blog: http://blog.csdn.net/rickshaozhiheng/article/details/53608168 *Email: zhiheng.rick@gmail.com *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
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞