动画是一款游戏不可缺少的一部分。在Unity中,我们可以直接使用Unity自带的动画系统来制作我们想要的动画,其操作相当便捷。
帧动画是2D像素游戏的主流,我将以帧动画为例记录我最近学习动画系统的一些收获。
Unity的动画系统有三个不可缺少的部分。第一,动画;第二,动画组件;第三,动画控制器。
动画和动画组件不难理解,动画是我们添加进Unity的资源文件,动画组件是添加进游戏物体的必要控件。
那么动画控制器是什么呢?
那不就是能控制动画的系统。
没错,但是如何控制呢?
首先我们需要知道为什么要有动画控制器这个东西。Unity中的动画和我们日常生活中理解的动画不太一样。在Unity中,动画是由一个个“动画片段”组成的,而不是我们小时候长达24分钟不间断的动画片。为了将这些“动画片段”组装成我们想要的动画,就需要动画控制器来判断各个动画片段什么时候该播放,什么时候不该播放。
也就是说,动画控制器其实就动画片段的播放流程控制器。
下面以实际的游戏工程来介绍Unity动画系统,涉及人物的移动,跳跃动画。
首先,我们需要为人物添加动画组件Animator。
第一个参数是Animation Controller,即动画控制器。
第二个参数是替身,我们做2D游戏的时候不需要关注这个。
其余的参数可以通过Unity代码手册查阅,本篇笔记不做修改。
有了动画组件,我们就需要一个动画控制器来绑定它。
在Project窗口右键Create -> Animation Controller。
可以在Animator窗口查看该控制器的具体内容(Windows->Animation->Animator)。
其中,Entry指动画开始,通常后面会接一个默认动画。
Any State指任何状态,后面接的动画任何状态都能跳转到。
Exit即退出,退出之后又会回到Entry。
将动画控制器拖入Animator组件中。
这样就完成了动画控制器和动画组件的绑定。
还记得Unity动画系统的三大组成部分吗?
动画,动画控制器,动画组件。
现在有控制器和组件,只缺动画了。
Unity为我们提供非常便捷的动画制作方式,通过连续播放一组图片从而达到动画效果。
接下来制作人物默认状态下的动画片段。
点击Create,选择好文件夹,创建人物第一个动画片段吧。
按住shift,选择一组图片拖入Animation中,一个动画片段就已经做好了。怎么样,是不是很简单?
修改采样率Samples,采样率越低,动画播放得越慢,通过不断调试来找到适合我们的采样率。
点击播放符号即可在场景中预览动画,每次预览完记得点一下Preview,结束预览状态。
一个动画片段显然不够我们使用,接下来我将需要的动画片段一次性创建好。
现在动画控制器中已经有了刚刚创建好的动画片段了。
先将PlayerJump删除,专注设计奔跑动画的逻辑关系。
右键PlayerIdle,选择Make Transition,创建一条过渡(转换)指示线,将其连接到PlayerRun,即人物奔跑的动画片段。
点击这条新建的转换指示线,可以设置其中的转换条件。
这个转换条件可以在Parameters中添加。
点击加号,可以看到有四种不同的转换条件类型,分别是浮点型,整型,布尔型和触发型。
现在不妨来思考一下我们什么时候需要播放人物动画。
没错,就是人物移动的时候。
那么和人物移动相关的变量有哪些可以作为条件变量的值呢?
速度是个不错的选项。
如果速度大于0,那么就播放人物动画。
有了想法,接下来就是实现了。
首先在Parameters中添加一个浮点型的参数velocityX。
接着选择转换指示线,将刚刚添加的参数加载进去。
同时建立一个PlayerRun返回PlayerIdle的转换指示线,条件相反。
这里有两个小问题。
第一个问题,我们的移动应该是连续不断的,不会随着动画的结束而恢复到默认状态。
因此,我们需要取消勾选Has Exit Time,让该动画完全受控于转换条件。
同时也可以取消过渡时间(如果值大于0会出现延迟效果)。
第二个问题,Unity在将一个变化的值和0比较时可能会出现一些小错误,为了减少这种错误,我们可以将播放动画的条件设置为velocityX大于0.1。
下面最后修改过后的设置图。
那么velocityX的值究竟如何和速度进行绑定呢?
现在就需要我们自己写脚本了,我在这里为人物新建了一个PlayerAnimation脚本,专门管理动画相关的代码。
思考我们需要获取哪些组件和变量。
首先是动画组件,只有获取动画组件才能为velocityX的值赋值。
其次是刚体组件,我们需要将刚体中X轴的速度传递个velocityX。
代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerAnimation : MonoBehaviour
{
private Animator anim;
private Rigidbody2D rb;
private void Awake()
{
anim = GetComponent();
rb = GetComponent();
}
private void Update()
{
anim.SetFloat("velocityX", Mathf.Abs(rb.velocity.x));
}
}
SetFloat方法的意思是将刚体X轴速度的绝对值传给velocityX,除了SetFloat外,还有SetBool、SetInt和SetTrrigger,除了SetTrigger,其余的都有两个参数,第一个参数是条件参数的名称,第二个参数是要传递的值。由于这个值需要实施检测,因此放在Update()中。
现在我们的人物已经可以自由奔跑了,接下来制作跳跃动画。
与奔跑动画不同,跳跃动画由4个不同的动画片段共同组成,每个动画片段表示一个跳跃的阶段。
在这种情况下,我们可以直接使用Unity自带的一个十分方便的操作——混合树(Blend Tree)。
在动画控制器中右键新建一个混合树。
点击混合数,在Inspector窗口中的添加四个Motion。
每个Motion对应一个跳跃的动画片段。
新建一个条件参数velocityY,记录Y轴方法人物的运动速度,并将Parameter修改为velocityY。
注意到现在动画片段的切换门槛不可以手动修改,这是因为我们选中了Automate Threshold,将其取消勾选就可以手动修改了。
接着仿照移动动画在脚本中添加velocityY的赋值就行了。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerAnimation : MonoBehaviour
{
private Animator anim;
private Rigidbody2D rb;
private CheckState checkState;
private void Awake()
{
anim = GetComponent();
rb = GetComponent();
checkState = GetComponent();
}
private void Update()
{
anim.SetFloat("velocityX", Mathf.Abs(rb.velocity.x));
anim.SetFloat("velocityY", rb.velocity.y);
anim.SetBool("isGround", checkState.isGround);
}
}
这样,跳跃动画就做好了。