3D动画教程
角色动画
在Unity中,角色动画是创建游戏的重要环节。相关内容可在“Unity手册 > 使用指南 > 创建游戏 > 角色动画”中找到。
动画系统特性
Unity的动画系统功能强大,允许开发者创建精美的动画角色。该系统支持动画合成、混合、添加动画、步调周期时间同步、动画层,还能控制动画回放的各个方面,如时间、速度、混合权重等。同时,它支持网格面每个顶点有1、2或4个骨骼,并且可以实现基于物理的布娃娃效果。
创建优化角色的建议
若要在Unity中创建性能优化的角色,建议阅读“Modeling Optimized Characters”页面上的教程,了解相关的最佳实践。
制作动画角色的要点
制作动画角色主要涉及两个方面:一是让角色在游戏世界中移动,二是为其添加相应的动画。本页面主要聚焦于动画部分。如果想了解更多关于角色移动的内容(如超级玛丽风格游戏或第一人称射击游戏中的角色移动),可查看“Character Controller”页面。
本页涵盖的主题
如果你想快速跳转至相关主题,本页涵盖以下内容:
- 导入角色动画
- 动画分割
- 多文件导入
- 反向运动学导入
- 插入到Unity场景
- 角色动画制作
- 动画混合
- 动画层
- 添加动画
你可以点击此处下载一个展示预设动画角色的示例演示。
导入动画
直接导入角色文件
首先,需要导入角色文件。Unity原生支持导入Maya(.mb或.ma)文件、Cinema 4D(.c4d)文件以及大多数动画包都能导出的fbx文件。点击此处可学习如何从你的建模/动画包中导出文件。
使用动画分割导入动画
对于动画师来说,最方便的工作方式是使用一个包含所有动画的单一模型。在导入动画模型时,可以定义每个动画部分由哪些帧组成。Unity会自动将动画分割成单个的动画片段(Animation Clips)。
例如:
- 走路动画:第1 - 33帧
- 跑步动画:第41 - 57帧
- 踢腿动画:第81 - 97帧
要导入动画,只需将模型放置在项目的“Assets”文件夹中,Unity会自动导入。在项目视图中选中该模型,然后在检视视图中编辑导入设置。
在导入设置中,“Split Animations”表用于告知Unity资源文件中的哪些帧构成了哪些动画片段。在这里指定的名称将用于在游戏中激活这些动画。
各参数含义如下:
- name:定义Unity中动画片段的名称。
- first frame:动画的起始帧,帧编号与创建动画的3D程序中的帧编号一致。
- last frame:动画的终止帧。
- loop frame:如果启用,会在动画末尾插入一个额外的循环帧,该帧与片段的第一帧匹配。当你想制作循环动画,且起始帧和终止帧不完全匹配时,可以使用此选项。
使用多模型文件导入动画
另一种导入动画的方法是遵循特定的命名方案。创建单独的模型文件,并使用“模型名字@动画名字.fbx”的命名约定。
例如,一个动画角色有四个动画文件: Unity会自动导入所有四个文件,并将所有动画收集到没有“@”符号的文件中。在上述示例中,“goober.mb”文件将自动设置为引用空闲、跳跃、走路和翻墙动画。
导入反向运动学
当从Maya导入使用反向运动学(IK)创建的动画角色时,需要在导入设置中勾选“Bake IK ; simulation”选项,否则角色的动画将无法正常播放。
将角色带入场景
导入模型后,可将对象从项目视图拖到场景视图或层次视图中,即可将动画角色添加到场景中。
角色的动画列表中可能有多个动画,但可能没有默认动画。可以通过将项目视图中的动画片段拖到角色(在层次视图或场景视图中)来为角色添加更多动画,这也会设置默认动画。点击播放按钮时,默认动画将开始播放。
角色动画制作
动画混合
在当今的游戏中,动画混合是确保角色动画平滑过渡的关键特性。动画师通常会创建单独的动画,如走路循环、跑步循环、空闲动画或射击动画。在游戏中,需要实现不同动画之间的平滑过渡。
在Unity中,可以在同一个角色上同时播放任意数量的动画,所有动画会进行混合或叠加以生成最终动画。
为了实现角色在空闲和走路动画之间的平滑混合,首先需要设置动画的循环模式为“Loop”,并关闭自动播放,确保脚本是控制动画播放的唯一方式。
以下是一个简单的角色动画脚本示例:
function Update () {
if (Input.GetAxis("Vertical") > 0.2) {
animation.CrossFade ("walk");
} else {
animation.CrossFade ("idle");
}
}
要使这个脚本运行,可按以下步骤操作:
- 通过“Assets->Create Other->Javascript”创建一个JavaScript文件。
- 将上述代码复制粘贴到该文件中。
- 将脚本拖到角色上(该角色必须是与动画关联的同一个GameObject)。
点击播放按钮后,按住上箭头键,角色将开始原地走路;释放按键后,角色将回到空闲姿势。
动画层
动画层是一个非常有用的概念,它允许对动画进行分组并设置权重优先级。在Unity的动画系统中,可以混合任意数量的动画片段,可以手动分配混合权重,也可以使用“animation.CrossFade()”方法自动处理权重。
混合权重在应用之前会进行归一化处理。例如,同时播放走路和跑步动画,且它们的权重都为1(100%),Unity在生成最终动画时会将权重归一化,即走路和跑步动画各贡献50%。
当同时播放两个动画时,有时需要为某个动画设置更高的权重。使用动画层可以更方便地实现这一目的。
以下是一个动画层的示例:假设有射击动画、空闲动画和走路循环动画。需要根据玩家的速度在走路和空闲动画之间进行淡入淡出切换,但当玩家射击时,只显示射击动画。
可以通过以下代码实现:
function Start () {
// 设置所有动画为循环状态
animation.wrapMode = WrapMode.Loop;
// 射击动画不循环
animation["shoot"].wrapMode = WrapMode.Once;
// 将空闲和走路动画放在较低层(默认层为0)
// 这样射击和空闲/走路动画在不同层,调用CrossFade时不会相互影响
// 由于射击动画在更高层,淡入时会替换空闲/走路动画
animation["shoot"].layer = 1;
// 停止已经播放的动画
animation.Stop();
}
function Update () {
// 根据按下的键,播放走路或空闲动画
if (Mathf.Abs(Input.GetAxis("Vertical")) > 0.1) {
animation.CrossFade("walk");
} else {
animation.CrossFade("idle");
}
// 射击
if (Input.GetButtonDown ("Fire1")) {
animation.CrossFade("shoot");
}
}
默认情况下,“animation.Play()”和“animation.CrossFade()”会停止或淡出同一层的动画。在大多数情况下,这正是我们所需要的。
添加动画和动画混合
添加动画和动画混合可以减少为游戏创建的动画数量,对于创建面部动画也非常重要。
例如,要创建一个在跑步和转弯时向两侧倾斜的角色,如果为每种情况都创建单独的动画,会大大增加工作量。而使用添加动画和混合技术,可以只创建向左倾斜和向右倾斜的动画,Unity会将这些动画叠加到走路、空闲或跑步循环动画之上。
以下是实现该效果的代码:
private var leanLeft : AnimationState;
private var leanRight : AnimationState;
function Start () {
leanLeft = animation["leanLeft"];
leanRight = animation["leanRight"];
// 将倾斜动画放在单独的层,避免其他CrossFade调用影响它
leanLeft.layer = 10;
leanRight.layer = 10;
// 设置倾斜动画为添加模式
leanLeft.blendMode = AnimationBlendMode.Additive;
leanRight.blendMode = AnimationBlendMode.Additive;
// 设置倾斜动画为ClampForever模式,到达片段末尾时不会自动停止
leanLeft.wrapMode = WrapMode.ClampForever;
leanRight.wrapMode = WrapMode.ClampForever;
// 激活动画并将权重设置为100%
leanRight.enabled = true;
leanLeft.enabled = true;
leanRight.weight = 1.0;
leanLeft.weight = 1.0;
// 测试时播放走路动画并设置为循环
animation["walk"].wrapMode = WrapMode.Loop;
animation.Play("walk");
}
function Update () {
var lean = Input.GetAxis("Horizontal");
// normalizedTime在片段的第一帧为0,最后帧为1
leanLeft.normalizedTime = -lean;
leanRight.normalizedTime = lean;
}
使用添加动画时,要确保在每个用于添加动画的变换上同时播放一些非添加动画,否则动画会叠加在最后一帧的结果上,这通常不是我们想要的效果。
程序控制动画角色
有时需要通过程序来控制角色的骨骼动画。例如,让角色的头部看向3D空间中的特定点,这可以通过脚本来实现。在Unity中,所有骨骼都是驱动蒙皮网格的Transform,因此可以像控制其他GameObject一样编写角色骨骼的脚本。
需要注意的是,动画系统会在“Update()”函数之后、“LateUpdate()”函数之前更新Transform。因此,如果要使用“LookAt()”函数,应该在“LateUpdate()”中调用,以确保真正覆盖动画效果。