- 博客主页:https://blog.csdn.net/zhangay1998
- 欢迎点赞 收藏 ⭐留言 如有错误敬请指正!
- 本文由 God Y.原创,首发于 CSDN
- 未来很长,值得我们全力奔赴更美好美好的生活✨
- 本篇文章将对Unity中的动画系统做一个基础的介绍
- 包括Animation和Animator的基础属性知识和实战演练来学习Unity中的动画系统
- 动画在游戏中的地位尤为重要,模型跟动画一般是成套的,可以有专门的建模师对游戏模型进行设计,然后加上一系列的动画进行模型动作设计~
就拿王者荣耀举例来说,在英雄单独介绍的界面,每次点开一个英雄都会有一个英雄出场动画,大家都知道传说皮肤和荣耀典藏的出场动画都特别炫酷,那这就是一个典型的动画了。
还有在游戏中英雄的待机动画,移动动画,普攻,释放技能等等,都是通过调用播放不同的动画来实现的
设计师们通过对每个人物骨骼的特点设计出不一样风格的动画效果,能让人眼前一亮,让每个英雄的动作都有自己的标志性,这就是一个极好的作品啦!
一般来说每个模型都有一系列独有的动画系列,具有相同骨骼类型的模型还能共用一套动画!
在游戏中,有些英雄的攻击模式比较相似,设计师们就可以偷懒让他们共用一个系列的动画啦~
那我们这次就来一起学习一下Unity中的动画系统吧!
- 在介绍Unity的动画之前,先来科普一下基础知识
- 大家都知道在Unity中有很多的游戏对象,所谓游戏对象就是场景中存在的一些个物体
- 而模型呢在Unity中算是一个特殊的游戏物体
专门做模型的软件也有挺多,较出名的类似3DMAX,Maya等等
模型的格式有很多种,比如 *.max、*.fbx、*.obj等等格式
在Unity中常用的模型格式就是后缀为 .fbx 的文件了
Unity中的动画系统有两个,一个是Animation,另一个是Animator
Legacy动画系统使用的是Animation组件,直接对动画片段进行操作
而Mecanim动画系统使用的是Animator组件,是对各动画片段之间的切换进行控制。
相对于老版Animation,新版的Animator加入了动画状态机和骨骼Avatar。
常用类介绍:
下图就是我导入的一个后缀为 .fbx 的模型,可以看到该模型子级目录中还有挺多东西,那就是他的结构组成啦~还有网格渲染和一个骨骼
有的模型还带有动画,类似下面这种
点击右边的播放按钮可以查看动画效果~
上面提到了Animation是Legacy动画系统使用的
由于Animation算是老版的动画系统,所以这里我们就简单介绍一下,然后做一个简单实例,更多的介绍留给新人——Animator
在unity的老版本中我们只有Animation组件,在4.6版本以后则增添了Animator组件
Animation:用于播放动画,老版中单独的一个Animation也可以完成动画的播放和切换,不过状态切换之类的需要程序猿代码控制。在新版中,状态管理部分交给了Animator;
双击图示红色框部分可以新建一个关键帧,中间三个就是我新建的关键帧,这个关键帧可以左右拖动,代表关键帧执行的时间节点
有小伙伴可能想问这个关键帧有什么用呢,请接着往下看,就知道它的作用了!
然后我们把这五个关键帧的Position.z分别设置成:0,1,0,-1,0
将图中那条白色竖线左右拖到关键帧上设置Position.z的属性即可,输完数值别忘了点回车,确认数值已经输上!
这样就达成了上图中的效果,炮筒前后移动一米,然后初末位置相同,形成一个简单的无缝循环动作。就达成我们的目的啦~
关键帧就是在一个我们指定的时间,将设置的动画属性修改成我们设置的值
上面五个关键帧,相当于五个时间节点,在每个时间节点都设置好了他们应该执行的属性
- 上面的步骤设置完成之后,就可以在想使用动画的地方调用啦~
- 下面是简单的动画播放和停止的调用方法
Play(“TankAnimation1” );,播放动画,传入参数为动画名字
Stop(“TankAnimation1”) ,停止动画,传入参数为动画名字
CrossFade(“TankAnimation1”, 0.5f); ,有过度的切换动画,传入参数(动画名字,过度时间)
- Animator是4.6版本以后出现的,Animator是动画控制器,控制Mecanim动画系统的接口,用来管理多个动画;
- Mecanim动画系统就是Animator
- Unity的动画系统是基于动画剪辑的概念,其中包含了特定对象如何随着时间改变其位置、旋转或其他属性的信息。
- 每个片段都可以看作是一个单一的线性录音。
- 来自外部来源的动画剪辑是由艺术家或动画师与第三方工具,如Max或Maya,或来自动作捕捉工作室或其他来源。
- 然后,动画剪辑被组织成一个被称为Animator Controller的类似于流程图的结构化系统。
- Animator控制器充当一个“状态机”,跟踪当前播放的剪辑,以及动画何时应该改变或混合在一起。
Controller :动画控制器(动画状态机)
Avatar: ⻣骼
Apply Root Motion: 应⽤根动作
Update Mode:动画的更新模式。
Normal:同步更新,动画速度与运行速度相匹配,运行速度慢,动画慢。
Animate Physics:动画是有物理的相互作用时,用此模式。
Unscaled Time:不成比例的时间,动画忽略当前的运行速度。
Culling Mode:动画的裁剪模式。
Always Animate:总是启用动画,不进行裁剪。
Cull Update Transforms:更新裁切。
Cull Completely:完全裁切。
其中骨骼与根动作这里不做研究,因为一般是建模师负责,我们用的时候不多
Controller 就要仔细研究一下了,因为他就是导致Animator强大的一个原因!
可以在这个面板右键创建一个Empty,新建的第一个成为默认动画状态!
也可以直接将动画从Project面板拖动到这个Animator Controller视图中~
点击这个State可以查看(Animation States)动画状态:
黄色显示的状态为默认状态,指状态机首次激活时所进入的状态。可以在其他状态上右击选择Set as Layer Default State命令改变默任状态。
在某一动画状态右击后选择Make Transition,然后选择过渡到的下一动画状态,即可建立过渡联系。
制作:在视图右击空白处后选择Create State -> From New Blend Tree,双击进入。
实例:
Blend Type(混合类型)
该内容部分知识参考文章 https://blog.csdn.net/NCZ9_/article/details/84639900
1、配置好⻣骼
2、裁剪好动画⽚段
3、创建动画控制器 AnimatorController
4、通过代码调整动画参数。从⽽达成过渡条件,实现动画切换
开始操作
新建一个Animator Controller,上面已经讲过了,这里再发一次~
并将这个Controller拖到Animator组件中~
双击打开Controller后,直接将动画从Project面板将动画片段拖动到这个Animator面板中即可
然后将他们之间的动画过渡关系设置好
如下图中,Aert为待机动画,Move为移动动画,ATK3为攻击动画
左边是Animation Parameters(动画参数),上面提到过~
CanMove是一个Bool值,用来控制执行移动动画
Attack是一个Trigger值,用来控制执行攻击动画
MovePlayerSpeed是一个Float值,用来控制移动动画的播放速度
待机动画向移动动画过渡设置::
待机动画向攻击动画过渡:
移动动画向攻击动画过渡:
但是到这里有的小伙伴可能就有些疑惑,为什么动画参数一个用Bool,一个用Trigger,还有一个用Float呢?
这个呢,是根据具体情况而定的
因为移动动画,使我们按下某个键后就一直执行的,所以用Bool值来进行移动的判定
但是攻击动画呢,是你按下去一次就执行一次,显然Trigger更适合攻击动画
使用float值呢是为了改变动画的播放速度,显然是一个数值,使用float是最好的选择啦!
这样的话在Unity视图方面就设置完成了,接下来就是写代码控制动画的播放了
直接上代码挂在我们的小猫咪身上就行啦!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CatAnimation : MonoBehaviour
{
[Header("移动速度")]
public float MoveSpeed = 1f;
[Header("旋转速度")]
public float TurnSpeed = 5f;
private Animator ani;
private float hor, ver;
private void Awake()
{
ani = GetComponent<Animator>();
}
private void Update()
{
hor = Input.GetAxis("Horizontal");
ver = Input.GetAxis("Vertical");
if (hor !=0 || ver !=0)
{
ani.SetBool("CanMove",true);
}
else
{
ani.SetBool("CanMove",false);
}
//判断当前角色是否正在播放移动动画
if (ani.GetCurrentAnimatorStateInfo(0).IsName("Move"))
{
//声明一个临时播放速度
float sp = 0;
if (ver >= 0)
{
if (Input.GetKey(KeyCode.LeftShift))
{
sp = 2;
}
else
{
sp = 1;
}
}
else
{
if (Input.GetKey(KeyCode.LeftShift))
{
sp = -2;
}
else
{
sp = -1;
}
}
//前后移动
transform.position += ver* transform.forward * Time.deltaTime * MoveSpeed;
ani.SetFloat("MovePlaySpeed",sp);
transform.eulerAngles += transform.up * TurnSpeed * hor;
}
if (Input .GetKeyDown(KeyCode.J))
{
ani.SetTrigger("Attack");
}
if (Input.GetKeyDown(KeyCode.LeftShift))
{
MoveSpeed *= 2;
}
if(Input.GetKeyUp(KeyCode.LeftShift))
{
MoveSpeed /= 2;
}
}
}
代码解析:
代码中在Awake中拿到Animator组件,在Update中定义了一个简单的移动和旋转的方法
然后通过判断 是否按下水平和垂直轴 来进行 是否播放移动动画的方法
如果按下任意一个WASD或者上下左右键,调用ani.SetBool(“CanMove”,true);进行播放移动动画
不然就执行ani.SetBool(“CanMove”,false);执行待机动画
然后对当前是否进行播放移动动画进行了一个判断:if (ani.GetCurrentAnimatorStateInfo(0).IsName(“Move”))
如果在播放移动动画,则按下Shift键时,对移动动画播放进行加速,并且加速小猫咪的移动速度,这样就可以让小猫咪的移动速度和动画播放速度更协调
不然的话小猫咪普通移动时的动画播放和加速移动时的动画播放就是一样的,显然不符合常理,之前所添加的MovePlayerSpeed属性就是为了如此!
再就是按下J键的时候调用 ani.SetTrigger(“Attack”);进行攻击动画的播放~
上动图,看效果!