UnityShaderUV动画讲解二:移动端序列帧播放

序列帧动画在游戏开发中非常常见,比如:2D动画,序列帧特效等等。

老规矩,先上效果

贴图如下:

原理:

ID的增长方式:U方向是从左到右,V方向是 从下到上;

那么每个字的坐标怎么的出来呢 ?

例如:“师”的编号ID是多少?

师的编号/横向的总数= 15/6=2.5;  

注意:程序计数是0开始计数,别算错了。

竖向ID为 即为 横向ID得出来的结果取整数部分 floor(2.5)=2;

横向ID: 整数ID减去 横向个数乘以纵向ID   

横向ID:  15-6*2=3;

那么师的ID为(3,2);(YY:当前 状态是 还只是他在UV里面的横竖 方向上的ID,别搞混了 )

            /*存储一下当前帧的ID; 注意这个ID的类型绝对不可能是fixed类型,
			但是感觉在PC段又没有问题,想想为什么?
			是因为PC端不管怎么申明类型都是以float执行的,而移动端就会改变成fixed类型,
			此类型的数据范围是-2到+2之间*/
            half _FpsID=0;
            //对ID取模约束数值在0~最大图像之间。
			_FpsID = _FpsID % (_UCount*_VCount);
			//ID向下取整
			_FpsID = floor(_FpsID);
		    // 纵横向ID = ID除以横向个数
			half indexY = floor(_FpsID / _UCount);

把原始UV 切割;

	//缩小UV,放大图像
	fixed2 AnimUV = float2(i.uv.x / _UCount, i.uv.y / _VCount);

我们重新回来获取“从”的位置 坐标空间   

坐标原理: (原始UV的U方向/U方向的个数,原始UV的V方向/V方向的个数)

结果即为: (1/6,1/3)  = (0.1666,0.3333);

注意:坐标是从(0,0)开始的,也就是实际上整个“从”的实际坐标是:

U :(0~0.1666);

V:(0~0.333.);

                      

往左继续增加坐标:

			//横向ID与横向个数获取偏移值累加给基础位置
			AnimUV.x += indexX / _UCount ;

“新”坐标空间即为:         
            AnimUV.x +=1/6 

     U方向结果:(0~0.1666)+0.1666  =(0.1666~0.3332)

同理 V方向坐标即为:

   AnimUV.y +=1/3 

但是咱们美术同学做图习惯是<写文章的方式写法,从做到右写,从上到下>

所以V方向坐标运算需要修改下:

			//(由上向下播放 )  如果纵向ID为0  总数-1 - 当前ID,ID越大,Y越小 。
			AnimUV.y +=(_VCount-1 - indexY )/ _VCount;

这样新的V坐标结果即为:

     AnimUV.y+=(3-1-1)/3 

    AnimUV.y+=0

V 方向结果为:  (0~0.3333)+0=  (0~0.3333)

完整代码如下:

Shader "Unlit/UV_FpsAnimation"
{
   Properties
    {
		[NoScaleOffset]
        _MainTex ("Texture", 2D) = "white" {}
		_PlaySpeed("PlaySpeed",float) = 1//播放速度 
        _UCount("_UCount",float) = 1 //序列帧水平总数
		_VCount("_VCount",float) = 1 //序列帧垂直总数
		 /* 这里是UnityUI面板得一个开关,通过变体_AUTOPLAY
		去控制是否开启播放*/
		 [Toggle] _AUTOPLAY("AutoPlay",Float) = 0	
    }
    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100
 
        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #pragma multi_compile_fog
            #include "UnityCG.cginc"
			//变体得启用
			#pragma shader_feature  _AUTOPLAY_ON
 
            struct appdata
            {
                half4 vertex : POSITION;
                fixed2 uv : TEXCOORD0;
            };
 
            struct v2f
            {
                fixed2 uv : TEXCOORD0;
                UNITY_FOG_COORDS(1)
                half4 vertex : SV_POSITION;
            };
 
            sampler2D _MainTex;
			fixed _PlaySpeed;
			fixed  _UCount;
			fixed	_VCount;
	        /*存储一下当前帧的ID; 注意这个ID的类型绝对不可能是fixed类型,
			但是感觉在PC段又没有问题,想想为什么?
			是因为PC端不管怎么申明类型都是以float执行的,而移动端就会改变成fixed类型,
			此类型的数据范围是-2到+2之间*/
            half _FpsID=0;
			
            v2f vert (appdata v)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                UNITY_TRANSFER_FOG(o,o.vertex);
                return o;
            }
 
            fixed4 frag (v2f i) : SV_Target
            {
		
				//判断动画播放是否开启
			#ifdef  _AUTOPLAY_ON
             //当前ID累加 ,流逝时间每秒乘以播放速度
				_FpsID += _Time.y*	_PlaySpeed;
	         #endif
            //对ID取模约束数值在0~最大图像之间。
			_FpsID = _FpsID % (_UCount*_VCount);
			//ID向下取整
			_FpsID = floor(_FpsID);
		    // 纵横向ID = ID除以横向个数
			half indexY = floor(_FpsID / _UCount);
			//横向ID = ID减去 横向个数乘以纵向ID
            half indexX = _FpsID - _UCount * indexY;
			//缩小UV,放大图像
			fixed2 AnimUV = float2(i.uv.x / _UCount, i.uv.y / _VCount);
			//横向ID与横向个数获取偏移值累加给基础位置
			AnimUV.x += indexX / _UCount ;
			/*同理竖向播放如下 
			AnimUV.y +=indexY / _YSum;*/
			//(由上向下播放 )  如果纵向ID为0  总数-1 - 当前ID,ID越大,Y越小 。
			AnimUV.y +=(_VCount-1 - indexY )/ _VCount;
			//用新UV显示贴图
			fixed4 col = tex2D(_MainTex, AnimUV);
			//透明剔除,硬裁剪,节约性能,当然特效类的火焰等可能需要半透明处理。
			   clip(col.a - 0.5);           
                UNITY_APPLY_FOG(i.fogCoord, col);
				return col;
            }
            ENDCG
        }
    }

}

  • 16
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值