unity3d 克服不支持gif,实现动画
许久未接触 Unity,今天来学习 Unity 简单贴图动画的应用。
简单贴图动画脚本实现
代码示例
// 声明一个数组,用于存放贴图
// 声明后,在 Inspector 中会看到一个名为 frames 的数组
// 数组的长度可自行设置,若设置为 1,则代表只有 1 张图,可将一张 Texture 拖入;设置为 2 则代表 2 张图,以此类推
var frames : Texture[];
// 声明帧率(fps),即每秒播放的帧数,该值会影响动画的速度
var framesPerSecond = 10;
function Update() {
// 数组的索引,根据时间改变
// 当前时间乘以 fps 后与总帧数取余,得到的结果即为播放的当前帧
// 随着 Update 函数的更新,该索引值也会不断变化
var index : int = (Time.time * framesPerSecond) % frames.Length;
// 渲染当前贴图
renderer.material.mainTexture = frames[index];
}
使用方法
将上述脚本新建并保存,然后创建一个 Cube 或者平面,把脚本拖到该对象上,接着设置动画的贴图,最后点击 Play 按钮即可进行测试。
Unity 实现动态贴图的方法
由于 Unity 不支持 GIF 动画贴图,所以目前在 Unity 中实现动态贴图有以下两种方法:
方法一:关键帧图片序列加载
将图片导入成关键帧图片序列(类似 0, 1, 2...),然后使用脚本根据时间逐帧加载贴图。
方法二:大图偏移实现动画
将动画里面的关键帧画在一张大图上,然后使用 OFFSET 来根据时间决定贴图的显示位置,从而实现图片改变的动画效果。
以下是一个简单的脚本示例,翻译自 Wiki:
// 声明整个 Texture 的分布情况,这里表示 4 行 4 列,共 4 个动画
var colCount: int = 4;
var rowCount: int = 4;
// 声明想要播放的动画起始位置
// 例如,rowNumber = 0 且 colNumber = 0 代表红色第一个笑脸
// rowNumber = 3 且 colNumber = 0 代表黄色第一个笑脸
var rowNumber : int = 0; // 从 0 开始计算
var colNumber : int = 0; // 从 0 开始计算
var totalCells: int = 4;
var fps: int = 10;
var offset: Vector2;
// 更新动画,传递参数给 SetSpriteAnimation() 函数
function Update () {
SetSpriteAnimation(colCount, rowCount, rowNumber, colNumber, totalCells, fps);
}
// 设置动画
// 参数说明:贴图总列数、总行数、指定动画起始帧所在行号、列号、动画总帧数、帧率
function SetSpriteAnimation(colCount : int, rowCount : int, rowNumber : int, colNumber : int, totalCells : int, fps : int) {
// 计算索引
var index : int = Time.time * fps;
index = index % totalCells;
// 每个单元的大小
var size = Vector2 (1.0 / colCount, 1.0 / rowCount);
// 分割成水平和垂直索引
var uIndex = index % colCount;
var vIndex = index / colCount;
// 颠倒 V,让贴图正过来,实现所见即所得
offset = Vector2 ((uIndex + colNumber) * size.x, (1.0 - size.y) - (vIndex + rowNumber) * size.y);
renderer.material.SetTextureOffset ("_MainTex", offset);
renderer.material.SetTextureScale("_MainTex", size);
}
Unity 文件夹图像资源的读取
需要注意的是,文件以及文件夹必须寄宿在 Resources 目录下,才能顺利调用 Resources.Load() 和 Resources.loadAll() 这两个函数来获取所需的图像文件。
以下是一个示例代码:
public class GUITest : MonoBehaviour {
// 用于存储单张贴图
private Texture2D texSingle;
// 用于存储一组贴图
private Texture2D[] texAll;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void OnGUI() {
// 加载一张贴图的按钮
if (GUI.Button(new Rect(0, 10, 100, 50), "加载一张贴图")) {
if (texSingle == null) {
// 加载单张贴图,这里不需要加后缀
texSingle = Resources.Load("single/0") as Texture2D;
}
}
// 加载一组贴图的按钮
if (GUI.Button(new Rect(0, 130, 100, 50), "加载一组贴图")) {
if (texAll == null) {
var textures = Resources.LoadAll("textures");
int countAll = textures.Length;
texAll = new Texture2D[countAll];
for (int i = 0; i < countAll; i++) {
// 修正原代码错误,将 textures[i] 转换为 Texture2D 类型赋值给 texAll[i]
texAll[i] = textures[i] as Texture2D;
}
}
}
// 绘制单张贴图
if (texSingle != null) {
GUI.DrawTexture(new Rect(110, 10, 80, 80), texSingle, ScaleMode.ScaleToFit, true, 0);
}
// 绘制一组贴图
if (texAll != null) {
int countOfAll = texAll.Length;
for (int i = 0; i < countOfAll; i++) {
// 修正原代码错误,绘制 texAll[i]
GUI.DrawTexture(new Rect(110 + i * 80, 130, 80, 80), texAll[i], ScaleMode.ScaleToFit, true, 0);
}
}
}
}
通过上述内容,我们可以在 Unity 中克服不支持 GIF 的限制,实现动画效果,并且能够正确读取文件夹中的图像资源。