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按钮才会亮。我刚开始时经常忘了选对象,还以为是编辑器卡了。

小技巧: 如果你做的是2D精灵动画,建议把Sprite Renderer组件挂好再创建动画。否则后面还要手动绑定,挺麻烦的。

4.2 创建Animation Clip:从零到动

创建Animation Clip其实很简单。选中你的角色,打开Animation窗口,点击“Create”。系统会让你选一个保存路径,我建议在项目里建一个 Animations 文件夹,专门放这些片段。

创建好后,你会看到时间轴上出现了一条绿色的线。这就是当前帧的位置。你可以拖动它,也可以直接在某个时间点添加关键帧。

举个例子,我想让一个精灵原地闪烁。操作步骤是这样的:

  1. 选中精灵对象
  2. 在Animation窗口,把时间轴拖到0:00
  3. 点击“Add Property”,选择 Sprite Renderer > Color
  4. 把颜色设为白色,点击那个菱形小按钮(记录关键帧)
  5. 把时间轴拖到0:10
  6. 把颜色设为红色,再次点击菱形按钮
  7. 把时间轴拖到0:20
  8. 把颜色设回白色,再点一次

好了,一个闪烁动画就做好了。你点击播放按钮试试看?

核心要点: Animation Clip记录的是属性随时间的变化。不只是位置、旋转、缩放,任何组件上的属性都可以做动画。比如透明度、颜色、甚至脚本里的public变量。

我在项目中遇到过一个问题:动画播放完后,角色停在最后一帧,而不是回到初始状态。这是因为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拖进来,从“待机”拖一条线到“走路”,再从“走路”拖一条线回“待机”。这样角色就能在两个状态间切换了。

注意: 默认情况下,Animator Controller会播放第一个你拖进去的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平台跳跃角色时,状态机大概是这样的:

  1. Idle(待机)—— 默认状态
  2. Run(跑步)—— 条件:isMoving == true
  3. Jump(跳跃)—— 条件:isJumping == true
  4. Fall(下落)—— 条件:velocity.y < 0
  5. Attack(攻击)—— 条件:Trigger "Attack"

每个状态之间都有过渡线,并且设置了对应的条件。你想想看,这样角色就能根据玩家的输入,流畅地在各种动作间切换了。

避坑指南: 我曾经把过渡条件设得太宽松,结果角色一边走路一边攻击,动作全混在一起了。后来我加了一个“是否在攻击中”的Bool,攻击时锁定其他动作,问题就解决了。

4.6 实战小技巧:让动画更自然

最后分享几个我常用的技巧:

  • 过渡时间别设0:两个动画之间留一点点过渡时间(0.1秒左右),动作会更流畅。完全没过渡会显得很生硬。
  • 用Blend Tree做平滑过渡:如果你有多个方向的走路动画(上下左右),可以用Blend Tree来混合,这样角色转向时不会突然跳帧。
  • 动画事件:在Animation窗口里,可以在特定帧添加事件。比如在攻击动画的中间帧,触发一个伤害判定的函数。这个我后面会专门讲。
  • 记得勾选“Has Exit Time”:这个选项的意思是“等当前动画播完再切换”。对于攻击、受伤这类动作,一般要勾上。对于移动这种可以随时打断的,就别勾。

好了,2D动画系统的基础就这些。你只要把Animation Clip、Animator Controller和状态机这三样东西搞明白,大部分2D游戏的动画需求都能应付。下一章我们会聊更高级的动画混合和分层,到时候再深入。