开启辅助访问
 找回密码
 注册帐号

扫一扫,访问微社区

教程分享

关注:706

当前位置:游戏蛮牛 技术专区 教程分享

查看: 837|回复: 0

[基础知识] Unity3D 纹理的精灵动画效果

[复制链接]  [移动端链接]
7日久生情
4301/5000
排名
2350
昨日变化
4

1646

主题

1657

帖子

4301

积分

Rank: 7Rank: 7Rank: 7Rank: 7

UID
132510
好友
17
蛮牛币
65419
威望
0
注册时间
2015-12-24
在线时间
352 小时
最后登录
2017-6-20
发表于 2016-10-10 11:46:16 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?注册帐号

x
  精灵动画,顾名思义是一种动画效果,我们用到的贴图是类似胶卷一样的,把每一帧都放在一张图上,

  然后通过变换uv值进行位移切换,

  如果你之前没有进行过uv相关的变换,可以查看上一篇文章 unity3d 纹理贴图移动特效

  首先我们需要一个张这样的贴图

20141208140533721.png

  然后建立一个shader

  先声明变量

  _TexWidth  贴图总宽度

  _CellAmount  一张图上包含几个动作(有几个小图片)

  _Speed  动画的速度

  [cpp] view plain copy

  Properties {

  _MainTex ("Base (RGB)", 2D) = "white" {}

  _TexWidth ("Sheet Width", float) = 0.0

  _CellAmount ("Cell Amount", float) = 0.0//有几个画面

  _Speed ("Speed", Range(0.01, 32)) = 12

  }

  主要的操作也是在surf函数中进行

  需要一点数学的知识。。。。

  先浏览一下局部变量

  float2 spriteUV   贴图的uv坐标

  float cellPixelWidth     贴图中的一个小画面的宽度

  float cellUVPercentage     小画面占整个贴图的比率,小画面个数越少比率越大

  float timeVal    当前该显示的小图片位数(就是该显示哪个小图片了)

  float xValue   贴图uv中的x坐标值

  [cpp] view plain copy

  void surf (Input IN, inout SurfaceOutput o) {

  float2 spriteUV = IN.uv_MainTex;

  float cellPixelWidth = _TexWidth/_CellAmount;//一个小画面的宽度

  float cellUVPercentage = cellPixelWidth/_TexWidth;//小画面占大画面比率,个数越少比率越大

  float timeVal = fmod(_Time.y * _Speed, _CellAmount);

  timeVal = ceil(timeVal);//向上取整,得到一个小于CellAmount的整数

  float xValue = spriteUV.x;          xValue += cellUVPercentage * timeVal * _CellAmount;//

  xValue *= cellUVPercentage;//对uv进行缩放

  spriteUV = float2(xValue, spriteUV.y);

  half4 c = tex2D (_MainTex, spriteUV);

  o.Albedo = c.rgb;

  o.Alpha = c.a;

  }

  一个小画面的宽度

  = 总宽度 / 小图片数目

  cellPixelWidth = _TexWidth/_CellAmount;

  小画面占整个贴图的比率 = 一个小画面的宽度 / 整个贴图宽度

  cellUVPercentage = cellPixelWidth/_TexWidth

  对时间*速度与小图片数目取余,得到的就是一个小于小图片数目的数,正好就是当前该显示的图片位数

  fmod(x,y)取余函数,返回一个x/y 的浮点型余数

  timeVal = fmod(_Time.y * _Speed, _CellAmount)

  但是是fmod()得到的是一个浮点数值,不是一个整数值,

  我们就用ceil()这个函数对它进行向上取整

  timeVal = ceil(timeVal)

  初始化xValue贴图uv中的x坐标值

  float xValue = spriteUV.x

  进行偏移,得到当前小图片的uv位置

  xValue += cellUVPercentage * timeVal * _CellAmount

  然后必须对uv进行缩放才能看到一张小图片

  xValue *= cellUVPercentage

  然后得到最终uv值进行纹理渲染

  最终得到这样的结果:

20141208140943921.gif

  shader代码如下:

  [cpp] view plain copy

  Shader "Custom/testShader" {

  Properties {

  _MainTex ("Base (RGB)", 2D) = "white" {}

  _TexWidth ("Sheet Width", float) = 0.0

  _CellAmount ("Cell Amount", float) = 0.0//有几个画面

  _Speed ("Speed", Range(0.01, 32)) = 12

  }

  SubShader {

  Tags { "RenderType"="Opaque" }

  LOD 200

  CGPROGRAM

  #pragma surface surf Lambert

  float _TexWidth;

  float _CellAmount;

  float _Speed;

  sampler2D _MainTex;

  struct Input {

  float2 uv_MainTex;

  };

  void surf (Input IN, inout SurfaceOutput o) {

  float2 spriteUV = IN.uv_MainTex;

  float cellPixelWidth = _TexWidth/_CellAmount;//一个小画面的宽度

  float cellUVPercentage = cellPixelWidth/_TexWidth;//小画面占大画面比率,个数越少比率越大

  float timeVal = fmod(_Time.y * _Speed, _CellAmount);

  timeVal = ceil(timeVal);//向上取整,得到一个小于CellAmount的整数

  float xValue = spriteUV.x;          xValue += cellUVPercentage * timeVal * _CellAmount;//

  xValue *= cellUVPercentage;//对uv进行缩放

  spriteUV = float2(xValue, spriteUV.y);

  half4 c = tex2D (_MainTex, spriteUV);

  o.Albedo = c.rgb;

  o.Alpha = c.a;

  }

  ENDCG

  }

  FallBack "Diffuse"

  }

[发帖际遇]: BobbyKim 乐于助人,奖励 3 蛮牛币. 幸运榜 / 衰神榜

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册帐号

本版积分规则

快速回复 返回顶部 返回列表