如果游戏中,需要大量2D怪物,类似roguelike,割草的效果,就会有很多不同的帧动画,使用Animation,性能问题就很大,这个时候我们就需要使用gpu渲染,既能减少动画组件,还有效合批,再加上使用GPUInstance,轻松达到几千个怪物。另外这是一个序列帧动作,如果有多个角色动作,可以使用Texture2DArray,shader中的类型是2DArray。如有不对的地方,请指正。
本篇文章是一片转载文章,记录一下,通过学习文章的思路,自己放到项目使用,所以文章的代码没有测试,大家可以试试。
这一节介绍了 如何修改UV产生位移动画。
我们也可以通过修改UV产生序列帧播放。
使用数字来代表每个动画的位置
UV坐标分布为
数字增长方式 U是从左到右,V是从上倒下。
改下图片
使用一个符合UV增长方式的排列。
接下来使用上面的图片来制作Shader
需要添加3个参数来控制显示范围。
_X_Sum("序列水平个数",float) = 3
_Y_Sum("序列竖直个数",float) = 3
_ShowID("当前显示ID",float) = 0
首先需要吧_ShowID 的一个数据转换为二维坐标
首先获得V的坐标系数据
//对ID取模约束数值在0~最大图像之间。
_ShowID = _ShowID % (_X_Sum*_Y_Sum);
//显示ID默认是浮点数,向下取整获得整数
_ShowID = floor(_ShowID);
// 纵横向ID = 显示ID除以横向个数,使用Floor获取整数部分,就是纵向坐标
float indexY = floor(_ShowID / _X_Sum);
//横向ID = 整数ID减去 横向个数乘以纵向ID
float indexX = _ShowID - _X_Sum * indexY;
接下来吧0~1的原始UV约束进一个数字上 使用AnimUV记录
//依据个数缩小UV(放大图像)
float2 AnimUV = float2(i.uv.x / _X_Sum, i.uv.y / _Y_Sum);
获得默认位置显示“0”
添加左右横向偏移
//依据横向ID与横向个数获取偏移值累加给基础位置
AnimUV.x += indexX / _X_Sum ;
累加结果
添加上下纵向偏移
//(由下向上播放) Y累加变大
AnimUV.y +=indexY / _YSum;
一般这样就可以直接使用新的 AnimUV 获取图像了。
但是很多软件自动生成序列是这样的。
把
//(由下向上播放) Y累加变大
AnimUV.y +=indexY / _YSum;
改为
//(由上向下播放 ) 纵向偏移 = 纵向总数-1(获得正确的ID区间上限0~2) - 当前ID(获得反向纵向ID),ID越大,Y越小 。
AnimUV.y +=(_Y_Sum-1 - indexY )/ _Y_Sum;
带入刚才的计算
最后获得贴图
//用新UV坐标获取贴图
fixed4 col = tex2D(_MainTex, AnimUV);
--------------"_Time"是Shader内置时间变量-----------
_Time.x(0.05倍速)
_Time.y(正常速度)
_Time.z(2倍速)
_Time.w(3倍速)
Shader源码
Shader "CRLuo/CRLuo_Teaching14_Tex_Amin_G"
{
Properties
{
[NoScaleOffset]
_MainTex ("Texture", 2D) = "white" {}
_X_Sum("序列水平个数",float) = 3
_Y_Sum("序列竖直个数",float) = 3
_ShowID("当前显示ID",float) = 0
[Toggle(_AutoPlay_Key)] _AutoPlay_Key("自动播放",Float) = 0
_PlaySpeed("播放速度",float) = 1
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#pragma shader_feature _AutoPlay_Key
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float _X_Sum;
float _Y_Sum;
float _ShowID;
float _PlaySpeed;
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_Key
//当前ID累加 ,流逝时间(1秒)*播放速度(帧速率)
_ShowID += _Time.y* _PlaySpeed;
#endif
//对ID取模约束数值在0~最大图像之间。
_ShowID = _ShowID % (_X_Sum*_Y_Sum);
//ID向下取整
_ShowID = floor(_ShowID);
// 纵横向ID = ID除以横向个数,使用Floor获取整数部分,就是横向坐标
float indexY = floor(_ShowID / _X_Sum);
//横向ID = 整数ID减去 横向个数乘以纵向ID
float indexX = _ShowID - _X_Sum * indexY;
//依据个数缩小UV(放大图像)
float2 AnimUV = float2(i.uv.x / _X_Sum, i.uv.y / _Y_Sum);
//依据横向ID与横向个数获取偏移值累加给基础位置
AnimUV.x += indexX / _X_Sum ;
//(由下向上播放) 如果纵向ID为0 ,Y累加变大
//AnimUV.y +=indexY / _YSum;
//(由上向下播放 ) 如果纵向ID为0 总数-1 - 当前ID,ID越大,Y越小 。
AnimUV.y +=(_Y_Sum-1 - indexY )/ _Y_Sum;
//用新UV显示贴图
fixed4 col = tex2D(_MainTex, AnimUV);
//透明剔除
clip(col.a - 0.5);
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
}