《土豆荣耀》重构笔记(五)创建角色以及怪物的动画

前言

  在游戏中,角色和AI的移动都需要配上相应的动画,以免让玩家产生游戏中的角色或者AI在平移的不真实感。一般来说,角色和AI的动画都会比前面介绍的游戏背景动画复杂很多,因为角色和AI的动画既需要精心编辑动画让身体各个部位的运动看起来很真实,又需要协调身体各个部位的运动。本篇文章的主要内容,就是讲述如何使用Unity制作角色和怪物的动画。


创建角色和怪物

  在开始制作角色和怪物的动画之前,我们需要先创建角色和怪物。在Project窗口打开Sprites\Character目录,可以看到char_enemy_alienSlugchar_hero_beanMan并不是一张完整的图片,而是多张图片拼在一起的图集。点击char_hero_beanMan,在Inspector窗口我们可以看到它的Sprite ModeMultiple,这表示这张图片是多张图片拼接而成,Unity会自动帮我们切成多张单独的图片。当然,我们也可以点击Sprite Editor来决定自己要怎么切割图片,Sprite Editor的具体用法可见Unity的Sprite Editor。切割完成之后,点击char_hero_beanMan右下角的三角形图标,我们可以看到有许多张小图片以列表的形式展示出来,这些就是切割产生的图片,我们可以像使用普通Sprite一样使用它们

Multiple Sprite

  接着,我们在Hierarchy列表中创建一个Empty GameObject,将其命名为Player后,在它下面创建一个名为CharacterEmpty GameObject并将char_hero_beanMan切割得到的图片都拖拽到Character下。

Player的结构

  为了让Character下各个Sprite都能正常显示,我们还需要创建一个名为Character的Sorting Layer,该Sorting Layer与其他Sorting Layer的关系如下:

Sorting Layer

Player各个子物体的被修改的属性如下:

  • Character: Scale: (0.48, 0.48, 0.48)
  • bazooka:
    • Position: (0.234, 0.394, 0)
    • Sorting Layer: Character, Order In Layer: 0
  • body: Sorting Layer: Character, Order In Layer: 1
  • hat:
    • Position: (-0.4, 1.43, 0), Rotation: (0, 0, -5.724)
    • Sorting Layer: Character, Order In Layer: 2
  • leftEye
    • Position: (0.39, 0.892, 0)
    • Sorting Layer: Character, Order In Layer: 3
  • leftFoot
    • Position: (0.81, -1.63, 0)
    • Sorting Layer: Character, Order In Layer: 3
  • leftHand
    • Position: (0.937, -0.058, 0)
    • Sorting Layer: Character, Order In Layer: 3
  • rightEye
    • Position: (-0.212, 0.801, 0)
    • Sorting Layer: Character, Order In Layer: 3
  • rightFoot
    • Position: (-0.49, -1.87, 0)
    • Sorting Layer: Character, Order In Layer: 3
  • rightHand
    • Position: (-0.975, -0.386, 0)
    • Sorting Layer: Character, Order In Layer: 3
  • tache
    • Position: (-0.019, 0.173, 0)
    • Sorting Layer: Character, Order In Layer: 3

  接着,我们创建一个名为AlienSlugEmpty GameObject,然后在AlienSlug下创建一个名为CharacterEmpty GameObject,并将char_enemy_alienSlug切割得到的图片拖拽到Character下面。

AlienSlug的结构

AlienSlug各个子物体的被修改的属性如下:

  • Character: Scale: (0.4, 0.4, 0.4)
  • enemy1-eye:
    • Position: (0.06, 0.59, 0)
    • Sorting Layer: Character, Order In Layer: 0
  • enemy1-eyelid:
    • Position: (-0.07, 1.07, 0)
    • Sorting Layer: Character, Order In Layer: 1
  • enemy1-body:
    • Position: (0, 0, 0)
    • Sorting Layer: Character, Order In Layer: 2
  • enemy1-tail:
    • Position: (-1.52, -1.49, 0)
    • Sorting Layer: Character, Order In Layer: 1

  最后,我们创建一个名为AlienShipEmpty GameObject,然后在AlienShip下创建一个名为CharacterEmpty GameObject。因为char_enemy_alienShipSprite ModeSingle,因此我们直接将这张图片拖拽到AlienShip下的Character下并将CharacterScale设置为(0.4, 0.4, 0.4)即可。

AlienShip的结构


创建怪物的动画

  首先,我们在AnimationAnimator文件夹下都创建一个名为Enemy的文件夹用于保存怪物的动画和状态机。然后打开Animation Editor,在Hierarchy窗口选中AlienShip创建一个名为AlienShip.anim的动画,并将AlienShip.controller移动到Animator\Enemy文件夹下。创建完毕后,我们为AlienShip添加char_enemy_alienShip的Rotation为动画控制属性,然后添加关键帧。

AlienShip关键帧

  为了使动画在循环播放时顺畅播放,不产生明显的停滞感,我们不能在KeyFrame处对Animation Curve作平滑处理,因此这里,所有的KeyFrame的Tangent Type我们都设置为Auto

AlienShip新增的关键帧的属性值如下(起始帧和结尾帧不变,Tangent Type都为Auto):

  • KeyFrame 1:
    • frame: 15, Rotation: (0, 0, 4.8)
    • Tangent Type: Auto
  • KeyFrame 2:
    • frame: 30, Rotation: (0, 0, 0)
    • Tangent Type: Auto
  • KeyFrame 3:
    • frame: 45, Rotation: (0, 0, -4.8)
    • Tangent Type: Auto

  接着,我们用相同的办法创建一个名为AlienSlug.anim的动画。创建完毕后,我们为AlienSlug添加enemy1-eyelid的Positonenemy1-tail的Scale这两个动画控制属性,然后添加关键帧。

AlienSlug关键帧

  因为在眨眼和伸缩尾巴时,有短暂的停顿并不会影响动画效果,因此,所有的KeyFrame的Tangent Type我们都使用默认的Clamped Auto,以确保能产生一条光滑的曲线。

AlienSlug新增的关键帧的属性值如下(起始帧和结尾帧不变。Tangent Type都为Clamped Auto ):

  • KeyFrame 1:
    • frame: 20
    • enemy1-tail的Scale: (1.6, 1, 1)
    • Tangent Type: Clamped Auto
  • KeyFrame 2:
    • frame: 30
    • enemy1-eyelid的Rotation: (-0.07, 1.31, 0)
    • Tangent Type: Clamped Auto

创建角色动画

  角色的动画比较复杂,除了静止时的Idle动画,我们还需要创建行走时的Walk、跳跃时的Jump、射击时的Shoot和死亡时的Death。我们先从最简单的Idle动画做起。

  首先,我们在AnimationAnimator文件夹下都创建一个名为Player的文件夹用于保存角色的动画和状态机。然后打开Animation Editor,在Hierarchy窗口选中Player创建一个名为Idle.anim的动画,并将Player.controller移动到Animator\Player文件夹下。创建完毕之后,我们为Idle动画添加body的Position属性作为动画控制属性,然后添加关键帧。因为在Idle动画中,我们只在第30帧处添加了一个关键帧,切所有关键帧的Tangent Type为默认的Clamped Auto,所以添加的关键帧属性值参见下图。

Idle动画添加的关键帧

  创建完毕后,我们点击Create New Clip,创建一个名为Walk.anim的动画并将其保存在Animation\Player文件夹下。

创建新动画

  创建完毕之后,我们为Walk动画添加动画控制属性和关键帧。因为该动画精细程度要求不高,我们可以先将采样率从60减少到5,再添加动画控制属性。具体添加的动画控制属性见下图。

Walk动画的控制属性

Walk动画新增的关键帧的属性值如下(起始帧和结尾帧不变,Tangent Type都为Free Smooth + Flat):

  • KeyFrame 1:
    • frame: 1
    • leftFoot的Position: (0.15, -1.87, 0)
    • tache的Rotation: (0, 0, -3.25)
    • Tangent Type: Free Smooth + Flat
  • KeyFrame 2:
    • frame: 2
    • bazooka的Position: (0.33, 0.47, 0)
    • leftFoot的Position: (-0.56, -1.8, 0)
    • leftFoot的Rotation: (0, 0, -59.081)
    • leftHand的Position: (1.033, 0.018, 0)
    • rightFoot的Position: (0.56, -1.8, 0)
    • rightFoot的Rotation: (0, 0, 37.936)
    • rightHand的Position: (-1.07, -0.386, 0)
    • Tangent Type: Free Smooth + Flat
  • KeyFrame 3:
    • frame: 3
    • leftFoot的Position: (0.15, -1.87, 0)
    • Tangent Type: Free Smooth + Flat

  接着,我们继续创建一个名为Jump.anim的动画并将其保存在Animation\Player文件夹下。创建完毕之后,我们为Jump动画添加动画控制属性和关键帧。因为该动画精细程度要求不高,我们可以,我们可以先将采样率从60减少到10,再添加动画控制属性。具体添加的动画控制属性见下图。

Jump动画的控制属性

Jump动画修改的关键帧的属性值如下:

  • KeyFrame 0:
    • frame: 0
    • hat的Position: (-0.5, 1.6, 0)
    • leftFoot的Position: (1.07, -1.89, 0)
    • rightFoot的Position: (-0.73, -2.11, 0)
    • rightHand的Position: (-1.59, -0.58, 0)
    • Tangent Type: Free Smooth + Flat
  • KeyFrame 1:
    • frame: 从10移动到5,表示动画只有0.5s
    • Tangent Type: Free Smooth + Flat

  设置好Jump动画的关键帧之后,我们继续创建一个名为Shoot.anim的动画并将其保存在Animation\Player文件夹下。创建完毕之后,我们为Shoot动画添加动画控制属性和关键帧。Shoot动画所有关键帧的Tangent Type都为Free Smooth + Flat,因为Shoot动画只在第30帧处添加了一个关键帧,因此添加的关键帧属性值参见下图。

Shoot动画添加的关键帧

  最后,我们为角色创建和死亡相关的动画。首先新建Death.anim的动画并将其保存在Animation\Player文件夹下。创建完毕之后,我们为Death动画添加动画控制属性和关键帧。Death动画是最为复杂的动画,涉及到的动画控制属性较多,且创建的步骤有所不同。

Death动画的关键帧

Death动画的创建步骤:

  1. 添加动画控制属性
  2. 删除默认生成的结尾帧动画
  3. 添加在第10帧处的关键帧
  4. 添加在第4帧处的关键帧
  5. 添加在第15帧处的关键帧
    修改的关键帧的属性值如下:
  • KeyFrame 1:
    • frame: 4
    • Character的Rotation: (0, 0, 0)
    • Tangent Type: Clamped Auto
  • KeyFrame 2:
    • frame: 10
    • Character的Rotation: (0, 0, 24.075)
    • bazooka的Position: (-4.36, 0.65, 0)
    • bazooka的Rotation: (0, 0, 270.688)
    • bazooka的Scale: (0.85, 0.85, 0.85)
    • bazooka的Color: (255, 255, 255, 0)
    • hat的Position: (-1.52, 3.21, 0)
    • hat的Rotation: (0, 0, -214.424)
    • hat的Color: (255, 255, 255, 0)
    • leftEye的Position: (0.39, 0.97, 0)
    • leftFoot的Position: (1.03, -1.25, 0)
    • leftFoot的Rotation: (0, 0, 18.147)
    • leftHand的Position: (0.77, 0.56, 0)
    • rightEye的Position: (-0.11, 0.79, 0)
    • rightFoot的Position: (-0.3, -1.6, 0)
    • rightFoot的Rotation: (0, 0, 5.605)
    • rightHand的Position: (-0.86, 0.51, 0)
    • tache的Position: (0, 0.22, 0)
    • tache的Scale: (0.8, 0.8, 0.8)
    • Tangent Type: Clamped Auto
  • KeyFrame 3:
    • frame: 15
    • Character的Rotation: (0, 0, 65.82201)
    • Tangent Type: Clamped Auto

  角色死亡后,还需要一个掉落的动画。首先新建Falling.anim的动画并将其保存在Animation\Player文件夹下。创建完毕之后,我们为Falling动画添加动画控制属性和关键帧。需要注意的是,Falling动画是接着Death动画播放的,因此Falling动画的第一帧是以Death动画的最后一帧为基础的。此外,Falling涉及到的动画控制属性较多,具体有哪些动画控制属性参照下图。

Faliing动画的关键帧

Death动画修改的关键帧的属性值如下:

  • KeyFrame 0:
    • frame: 0
    • Character的Rotation: (0, 0, 65.82201)
    • bazooka的Color: (255, 255, 255, 0)
    • body的Rotation: (0, 0, 0)
    • hat的Color: (255, 255, 255, 0)
    • leftFoot的Position: (1.03, -1.25, 0)
    • leftFoot的Rotation: (0, 0, 18.147)
    • leftHand的Position: (0.77, 0.56, 0)
    • leftHand的Rotation: (0, 0, 0)
    • rightFoot的Position: (-0.3, -1.6, 0)
    • rightFoot的Rotation: (0, 0, 5.605)
    • rightHand的Position: (-0.86, 0.51, 0)
    • rightHand的Rotation: (0, 0, 0)
    • tache的Position: (0, 0.22, 0)
    • tache的Scale: (0.8, 0.8, 0.8)
    • Tangent Type: Clamped Auto
  • KeyFrame 1:
    • frame: 10
    • body的Rotation: (0, 0, -4.336)
    • leftFoot的Position: (1.06, -0.99, 0)
    • leftFoot的Rotation: (0, 0, 11.305)
    • leftHand的Position: (1.06, 0.9, 0)
    • leftHand的Rotation: (0, 0, 17.069)
    • rightFoot的Position: (-0.16, -1.91, 0)
    • rightFoot的Rotation: (0, 0, 6.283)
    • rightHand的Position: (-0.93, 0.28, 0)
    • rightHand的Rotation: (0, 0, -13.507)
    • Tangent Type: Clamped Auto
  • KeyFrame 2:
    • frame: 20
    • Character的Rotation: (0, 0, 65.82201)
    • leftFoot的Position: (1.15, -1.43, 0)
    • leftFoot的Rotation: (0, 0, -8.312)
    • leftHand的Position: (0.95, 0.17, 0)
    • leftHand的Rotation: (0, 0, -17.067)
    • rightFoot的Position: (-0.25, -1.61, 0)
    • rightFoot的Rotation: (0, 0, 19.564)
    • rightHand的Position: (-0.94, 0.59, 0)
    • rightHand的Rotation: (0, 0, 6.41)
    • Tangent Type: Clamped Auto

制作Prefab

  创建完所有角色和怪物的动画之后,我们还需要做一点小小的收尾工作。首先,我们在Assets文件夹下都创建一个名为Prefabs的文件夹,然后在Prefabs文件夹下都创建一个名为Character的文件夹,用于存放角色和怪物的Prefab。接着,我们将PlayerAlienSlugAlienShip这三个GameObject从Hierarchy窗口中拖拽到Project下的Assets\Prefabs\Character文件夹中,将它们做成Prefab。

制作Prefab


后言

  至此,创建角色和怪物动画的所有工作都已经完成。在制作动画的过程中,读者可以根据自己的喜好调整参数。最后,本篇文章所做的修改,可以在PotatoGloryTutorial这个仓库的essay3分支下看到,读者可以clone这个仓库到本地进行查看。


参考链接

  1. Unity的Sprite Editor
  2. Prefabs
  3. Creating Prefabs

《土豆荣耀》重构笔记(五)创建角色以及怪物的动画
https://asancai.github.io/posts/d483ec30/
作者
RainbowCyan
发布于
2018年12月26日
许可协议