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

来源:互联网 发布:詹姆斯琼斯 知乎 编辑:程序博客网 时间:2024/04/27 06:35

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


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

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

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


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

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


这里有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 200CGPROGRAM#pragma surface surf Lambertsampler2D _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 ) 就是游戏运行到现在有多少秒,每秒变动一次图片。



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

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

using UnityEngine;using System.Collections;public class SpriteSheetAnim : MonoBehaviour {    float cellIndex;// Use this for initializationvoid Start () {}// Update is called once per framevoid 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


0 0