2D游戏实质上就是图层叠图层的过程,在一张巨大的图层中,不停播放动画的过程。因此,序列帧动画和GIF在2D中占据真很重要的地位。如果拿Unity3D制作2D游戏,由于Unity3D不接受GIF动画,所以动画要按照最原始的游戏制作方式,利用序列帧大图完成。在《【Photoshop】合并一系列序列帧图片成序列帧大图》(点击打开链接)中,我曾经提到如何用常用的图片处理软件Photoshop cc将GIF图片转化为序列帧大图。下面则用一个例子来说明Unity3D中如何使用序列帧大图。本文不使用NGUI,用原生的UGUI。
如下图一张序列帧大图aa.png:
要最终在Unity3D完成如下简单的动画播放效果。可以用两个按钮来控制动画的播放。
和原本这张序列帧大图所代表的GIF是无异的!
一、场景布置
1、首先我们先新建一个2D游戏,而不是3D。如果是在做3D游戏,还用啥序列帧大图和GIF?当然要上骨骼动画了!
其实在Unity3D中2D和3D游戏制作中,最大的区别是主摄像机Main Camera的投影从发散投影perspective,变成了如下图的平行正射orthographic。让玩家从视觉上发生了深刻的改变。其余没什么区别,可以打开2D界面尽情创作。2D游戏还有一个好处,就是开发成本低,搞个GIF总比你搞个3D模型快多了,而且还不用考虑灯光这些奇奇怪怪的东西。
2、之后,我们在场景新建一个Sprite,同时在UI的已设置适应主摄像机的Canvas布置两个按钮一个PlayButton,一个StopButton,并在旗下的Text改名。
(1)对于Canvas,需要先设置贴合摄像机。
(2)之后再创作如下的UI。
3、接下来在Assets中新建一个Resources,放入我们的序列帧大图aa.png。
aa.png的属性设置如下,同时打开切割器Sprite Editor。
4、由于这张序列帧大图aa.png我自己很清楚是由一堆64x64的图片拼接出来的。所以在Type中选择网格Grid之后,像素Pixel Size输入64x64,直接完成即可。
则得到如下的局面。
二、脚本编写
直接给New Sprite赋予如下脚本。实质上在控制哪个毫秒,精灵New Sprite上放的是那张图片而已。这里没有使用Update()这个父进程去播放动画,利用一个协程对应一个GIF的控制,我认为更合适。关于Unity3D配合C#的协程使用,具体可以参考《【Unity3D】协程Coroutine的运用》(点击打开链接)。
这里唯一一个注意点是,大家可以看到,原来GIF只有46帧,序列帧大图是按8x8共64帧来配置的,所以注意会有空白,因此,在协程中要求播到46帧,则马上从0开始。
在协程中,停顿时间为1/fps秒,fps为刷新频率,也就是帧数,原始游戏是30,高清时代是60,现在貌似去到75,这个自己定好就行。
实质上本程序来来去去都是spriteRenderer.sprite = sprites[i];控制当前是数组那个元素而已,其实没有什么技术含量。
using UnityEngine;
using System.Collections;
public class AnimationController : MonoBehaviour
{
private Coroutine AnimationPlay;//播放协程
private Sprite[] sprites;//被切割的序列图数组
private SpriteRenderer spriteRenderer;//精灵控制器
void Start()
{
sprites = Resources.LoadAll("aa");//载入资源aa.png
spriteRenderer = GetComponent() as SpriteRenderer;//这东西在精灵身上自带的,直接拿就行
}
void Update()
{
}
//按钮动作
public void PlayButtonOnClick()
{
AnimationPlay = StartCoroutine(AnimationPlayThread(30));
}
public void StopButtonOnClick()
{
StopCoroutine(AnimationPlay);
}
//实质在控制什么时候在精灵上放那张被切割的小图而已
IEnumerator AnimationPlayThread(float fps)
{
int i = 0;
while (true)
{
if (i < 46)
{
spriteRenderer.sprite = sprites[i];
i++;
}
else
{
i = 0;
}
yield return new WaitForSeconds(1 / fps);
}
}
}