Unity Shaders and Effects Cookbook (2-2) 修改 UV 坐标实现 帧动画

在2D游戏中,如果要做动画效果,一般是让美术制作连续帧的动画,然后我们用代码控制图片连续播放,这样就实现了帧动画,在shader中也可以实现这个效果。

Unity Shaders and Effects Cookbook (2-2) 修改 UV 坐标实现 帧动画_第1张图片


在上一节中学习了 改变 UV 坐标 然后来实现水流效果,这一节 通过改变UV坐标来实现帧动画效果。

文章转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

美术给我们的帧动画的图可能是一张一张的小图,也可以是类似于下面的大图图集。


在 Shader 中实现帧动画的原理:

默认的,Shader 中的 UV 范围是 (0,1) ,也就是说默认的是整个图集 这张大图显示出来,如下图

Unity Shaders and Effects Cookbook (2-2) 修改 UV 坐标实现 帧动画_第2张图片


这里有9张小图 如果要显示 第一张小图,该怎么办?

只要把 UV的范围修改成 ( 0 , 1/9 ) 就是了,那么从 (0,1) 到 ( 0 , 1/9 ) ,只要乘以 1/9  就可以了。

然后根据Unity提供的内置变量 _Time.y 进行取整,每次 _Time.y 增加 1 就移动 1/9,然后加上位移,那么

从 0 - 1s 这个时间段,取整为 1 显示的都是 第一张图 ( 0 , 1/9 ) 的x 范围,即第一张小图。

从 1 - 2s 这个时间段, 取整为 2 显示的都是 第一张图 ( 1/9 , 2/9 ) 的x范围,即第二张小图。

文章转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

Shader完整代码

Shader "CookBookShaders/Sprite Sheet Anim" {
	Properties {
		_MainTex ("Base (RGB)", 2D) = "white" {}
	}
	SubShader {
		Tags { "RenderType"="Opaque" }
		LOD 200
		
		CGPROGRAM
		#pragma surface surf Lambert

		sampler2D _MainTex;


		struct Input {
			float2 uv_MainTex;
		};

		void surf (Input IN, inout SurfaceOutput o) 
		{
			fixed2 spriteUV = IN.uv_MainTex;

			float cellPercentage = 1.0 / 9; //每一个小图占百分比;

			float xValue=spriteUV.x;

			//UV默认是(0,1),就是说默认显示整个大图,我们要显示一个小图,UV要指定到(0,1/9)的范围;
			xValue=xValue*(1.0/9);

			//再对时间取整,如果 _Time.y 时间超过了1,就加一个小图这么宽的位移,也就是把x 指到下一个小图的范围。就显示出下一个小图
			xValue+=cellPercentage * ceil(_Time.y);  //_Time.y 等同于 Time.timeSinceLevelLoad,就是游戏运行时间

			//再赋值;
			spriteUV = float2(xValue,spriteUV.y);
			
			half4 c = tex2D (_MainTex, spriteUV);

			o.Albedo = c.rgb;
			o.Alpha = c.a;
		}
		ENDCG
	} 
	FallBack "Diffuse"
}

文章转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

这里再次提醒 _Time 是一个 float4变量,值为 值为 Time (t/20, t, t*2, t*3), t 等同于 Time.timeSinceLevelLoad,就是游戏开始运行时间。

所以我这里取的 _Time.y 就是游戏开始运行到现在的时间,ceil ( _Time.y ) 就是游戏运行到现在有多少秒,每秒变动一次图片。

Unity Shaders and Effects Cookbook (2-2) 修改 UV 坐标实现 帧动画_第3张图片



书上也提到,在计算 当前应该将 UV 偏移到第几张小图 这里,可以把这个计算移动到 CPU中,用以节省 GPU 。

那新建一个脚本,内容如下:

using UnityEngine;
using System.Collections;

public class SpriteSheetAnim : MonoBehaviour {

    float cellIndex;

	// Use this for initialization
	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () 
    {
	
	}

    void FixedUpdate()
    {
        cellIndex = Mathf.Ceil(Time.time);
        transform.renderer.material.SetFloat("_cellIndex", cellIndex);
    }
}

在 FixedUpdate 中计算,仍然是对 当前时间进行了取整,来计算出当前应该偏移到第几张图。

把脚本挂在 Quad 上。运行后效果同上面的图。

文章转自http://blog.csdn.net/huutu http://www.thisisgame.com.cn

另外书上的 Shader 代码写的太复杂……

其中用到了另一个内置函数 fmod:

fmod ( x, y) 返回 x / y 的余数,即 x % y ,符号同 x ,如果 y =0 那么结果不可预料


ceil ( x ) 对 x 向上取整,如 ceil ( 0.6 ) == 1 。


示例工程打包下载:

http://pan.baidu.com/s/1skqBKmx


你可能感兴趣的:(unity3d,shader,帧动画)