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