4、2D 动画系统基础:Animation窗口、创建Animation Clip、Animator Controller、动画参数与状态机
做2D游戏,动画是灵魂。一个角色动不起来,玩家会觉得像在操作纸片。我最早做2D项目时,对动画系统一知半解,结果角色走路像在滑冰——脚没动,人却平移了。后来才明白,Unity的动画系统其实很强大,关键是要理解它的几个核心组件。
今天我们就来拆解一下。说白了,Unity的2D动画系统就三样东西:Animation Clip(动画片段)、Animator Controller(动画控制器)和状态机。你只要搞懂这三者的关系,2D动画这块基本就通了。
4.1 Animation窗口:你的动画工作台
先打开Animation窗口。路径是 Window > Animation > Animation,或者直接按 Ctrl+6。我个人习惯把它固定在编辑器下方,和Console放一起,方便随时调。
这个窗口长什么样?左边是层级列表,右边是时间轴。你选中一个游戏对象,点击窗口里的“Create”按钮,就能新建一个Animation Clip。嗯,这里要注意:只有选中了对象,Create按钮才会亮。我刚开始时经常忘了选对象,还以为是编辑器卡了。
4.2 创建Animation Clip:从零到动
创建Animation Clip其实很简单。选中你的角色,打开Animation窗口,点击“Create”。系统会让你选一个保存路径,我建议在项目里建一个 Animations 文件夹,专门放这些片段。
创建好后,你会看到时间轴上出现了一条绿色的线。这就是当前帧的位置。你可以拖动它,也可以直接在某个时间点添加关键帧。
举个例子,我想让一个精灵原地闪烁。操作步骤是这样的:
- 选中精灵对象
- 在Animation窗口,把时间轴拖到0:00
- 点击“Add Property”,选择
Sprite Renderer > Color - 把颜色设为白色,点击那个菱形小按钮(记录关键帧)
- 把时间轴拖到0:10
- 把颜色设为红色,再次点击菱形按钮
- 把时间轴拖到0:20
- 把颜色设回白色,再点一次
好了,一个闪烁动画就做好了。你点击播放按钮试试看?
我在项目中遇到过一个问题:动画播放完后,角色停在最后一帧,而不是回到初始状态。这是因为Animation Clip默认的“Wrap Mode”是“Once”。你可以在窗口右下角找到这个设置,改成“Loop”就能循环播放了。
4.3 Animator Controller:动画的大脑
单个Animation Clip只能做一件事。但游戏里的角色要走路、跳跃、攻击、受伤……这些状态怎么切换?这就轮到Animator Controller出场了。
创建方式也很简单:在Project窗口右键,选择 Create > Animator Controller。我习惯把它和Animation Clip放在同一个文件夹里。
双击打开Animator Controller,你会看到一个叫“Animator”的视图。这个视图里默认有一个“Any State”和一个“Entry”节点。别被吓到,其实很简单。
你只需要做两件事:
- 把Animation Clip拖进来——每个Clip会变成一个状态节点
- 创建过渡线——从一个状态拖到另一个状态,表示可以切换
比如,我做一个“待机”和“走路”的切换。把两个Clip拖进来,从“待机”拖一条线到“走路”,再从“走路”拖一条线回“待机”。这样角色就能在两个状态间切换了。
4.4 动画参数:控制切换的条件
光有过渡线还不够。你总不能让角色自己决定什么时候走路吧?我们需要用参数来控制。
在Animator窗口左侧,有个“Parameters”标签。点开它,点击“+”号,你可以添加四种参数:
| 参数类型 | 用途 | 我常用的场景 |
|---|---|---|
| Float | 浮点数,比如速度、方向 | 根据移动速度切换走路/跑步 |
| Int | 整数,比如生命值、阶段 | Boss战的不同阶段 |
| Bool | 布尔值,真/假 | 是否在地面、是否攻击 |
| Trigger | 触发器,用一次就重置 | 攻击、受伤这类一次性动作 |
我个人最常用的是Bool和Trigger。比如我加一个Bool参数叫 isMoving,然后在“待机”到“走路”的过渡线上,设置条件为 isMoving == true。反过来,从“走路”到“待机”的条件设为 isMoving == false。
在代码里怎么控制?很简单:
// 获取Animator组件
Animator anim = GetComponent<Animator>();
// 设置Bool参数
anim.SetBool("isMoving", true);
// 触发Trigger
anim.SetTrigger("Attack");
我曾经踩过一个坑:用Trigger时,如果连续触发两次,第二次可能会被忽略。原因是Trigger在同一个帧里只能触发一次。解决办法是加一个短暂的延迟,或者改用Bool配合协程来手动重置。
4.5 状态机:动画的决策逻辑
状态机这个词听起来高大上,其实就是一个“有限状态机”。说白了,就是告诉角色:在什么条件下,切换到什么状态。
在Animator Controller里,每个节点就是一个状态,每条线就是一个过渡。你可以把状态机想象成一张地图:
- Entry:起点,决定第一个播放哪个动画
- Any State:从任何状态都可以出发的过渡,适合做“受伤”这种打断动作
- Exit:退出状态机,一般用不到
我做一个2D平台跳跃角色时,状态机大概是这样的:
- Idle(待机)—— 默认状态
- Run(跑步)—— 条件:isMoving == true
- Jump(跳跃)—— 条件:isJumping == true
- Fall(下落)—— 条件:velocity.y < 0
- Attack(攻击)—— 条件:Trigger "Attack"
每个状态之间都有过渡线,并且设置了对应的条件。你想想看,这样角色就能根据玩家的输入,流畅地在各种动作间切换了。
4.6 实战小技巧:让动画更自然
最后分享几个我常用的技巧:
- 过渡时间别设0:两个动画之间留一点点过渡时间(0.1秒左右),动作会更流畅。完全没过渡会显得很生硬。
- 用Blend Tree做平滑过渡:如果你有多个方向的走路动画(上下左右),可以用Blend Tree来混合,这样角色转向时不会突然跳帧。
- 动画事件:在Animation窗口里,可以在特定帧添加事件。比如在攻击动画的中间帧,触发一个伤害判定的函数。这个我后面会专门讲。
- 记得勾选“Has Exit Time”:这个选项的意思是“等当前动画播完再切换”。对于攻击、受伤这类动作,一般要勾上。对于移动这种可以随时打断的,就别勾。
好了,2D动画系统的基础就这些。你只要把Animation Clip、Animator Controller和状态机这三样东西搞明白,大部分2D游戏的动画需求都能应付。下一章我们会聊更高级的动画混合和分层,到时候再深入。