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

@TOC


前言

  在游戏中,角色和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
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,175评论 5 466
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,674评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,151评论 0 328
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,597评论 1 269
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,505评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,969评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,455评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,118评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,227评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,213评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,214评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,928评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,512评论 3 302
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,616评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,848评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,228评论 2 344
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,772评论 2 339

推荐阅读更多精彩内容