Unity3D FPS游戏敌人动画控制详解
Unity3D FPS游戏敌人动画控制详解
本篇文章将详细介绍如何在Unity3D中为FPS游戏中的敌人添加动画控制。文章将从Unity动画控制的基础概念开始,逐步讲解如何使用Animation、Animator和Animator Controller来实现动画切换,并提供具体的代码示例。
Unity动画控制
Animation、Animator和Animator controller
Unity动画控制关键在于理解Animation、Animator和Animator controller,搞懂三者关系和如何实现,对Unity基本的动画控制就没问题了。
Animation就是一个动画片段,例如说行走、跑步和攻击等动画。可以通过在不同关键帧播放不同的图片,来实现动画,例如下面idle默认动画。
Animator是游戏中动画控制的一个组件,包含了Animator controller、Avatar、Apply Root Motion、Update Mode和Culling Mode等属性来控制动画。
- Avatar:Unity的替身系统,主要是用来3D人体动画的复用,在骨骼、网格、动画、Avatar、材质贴图中有比较具体的介绍。
- Apply Root Motion:有些动画会带有位移,勾选了带动画位移。
- Update Mode:动画更新模式,Normal表示使用Update进行更新也就是fps同步、Animate Physics表示和fixed unpdate同步(物理检测)、Unscaled Time和Normal一样但是不考虑Time scale(游戏运行速度比例)。
- Culling Mode:Cull剔除,也就是在摄像机视野外面的时候会做什么操作,Always Animate进行动画播放的更新、Cull Update Transform停止动画播放但是位置会继续更新、Cull Completely停止动画的所有更新。
其中Animator中比较重要的属性是Animator controller,是用来控制不同的Animation之间切换和叠加。主要有两个功能Layers和Parameters,Layers可以设置多层级动画叠加,Parameters则是设置参数进行转换。它是一个有限状态机,通过一些参数控制能够进行状态的切换。
例如下图中,实现从默认Idle状态切换到Jump状态,可以通过Bool参数ground为false来切换。
2D 动画
很早之前我写的Unity2D系列有提过动画控制,分别是博客为角色添加动画以及动画状态切换。这两篇博客中有详细的2D动画制作到控制的具体细节。2D动画可以通过不同帧播放不同的图片来实现,也可以通过骨骼动画来实现。3D动画就骨骼动画实现了。
3D 动画
FPS系列开篇第一篇的时候,就对3D模型相关的内容做了基础入门讲解,Unity3D学习FPS游戏(1)获取素材、快速了解三维模型素材(骨骼、网格、动画、Avatar、材质贴图)。
通过该篇博客,可以对3D模型相关的预制体结构、骨骼、网格、材质贴图、Avatar还有动画有基本理解。3D模型动画控制是通过骨骼动画来实现的,打开打开HoverRobot的一个Animation动画,可以发现骨骼动画中记录了每个时间点骨骼的变化。骨骼动画是通过移动模型中骨骼位置来实现的。
前面骨骼动画的原理中,动画和预制体中骨骼名字是一一对应的,但是不同的人做的模型骨骼名字会不同,这就导致动画也无法复用。于是就有了Avatar替身系统,主要针对常见的人形模型,可以把做好的模型骨骼都映射到人形Avatar中,这样不同模型都可以基于Avatar实现名字统一,从而实现动画复用。
敌人动画控制
获取Animation素材
3D模型的Animation通常不是我们程序做的,可以用素材现成提供好的。在FPS-Animation-HoverBot中可以找到已经提供好的动画素材。点击其中某一个Animation,右边的inspector可以预览动画的效果。
Animator controller动画切换
Layer设计
为什么需要设计Layer?
我们要先分好动画的Layer层级,该功能主要是用于动画的叠加,也就是有些动画是可以同时发生的。举例,玩fps时候,可以边走路边持枪,实际上是走路和持枪动画的叠加。这种动画组合,常常会把走路Layer只控制脚,而持枪Layer只控制手臂,做Avatar Mask来防止动作互不干扰。这样美术就可以不用单独出一套动作。
如何设计Layer?
所以我们要区分一些,有些动画是可以叠加的。想想那些动画是没有前后关联,主要是受伤和别的动作都没有前后关联。前面设计的时候敌人AI的时候,移动和攻击是有关联,攻击玩家时需要先停止移动。是否受伤和移动攻击都没有关系,
所以我们可以分成两个个Layer,分别是Base以及Damaged(受伤)。
创建Animator controller
在Animation文件夹下,新建一个Animator controller命名为HoverBot_AnimatorController。建两个个Layer,默认自带Base Layer,再新建一个Damaged Layer。
状态转换设计
分好了Layer,就要设置好每个Layer中动画状态的转换关系。先确定有多少个状态,然后再去设计状态之间转换控制参数。
Base Layer
有三种状态,不动Idle、移动RunFoward以及攻击Shoot。把对应的Animation拖到Base Layer中。
创建过渡:右键状态(State)模块,可以拉出过渡(Transition)箭头连接到别的状态模块。三个状态之间都是可以互相过渡的状态。添加Parameter进行过渡控制。设置两个参数变量,进行控制分别是speed(float)和isShoot(bool)。过渡规则:speed速度如果大于0.001就是跳到RunFoward状态,小于就跳出RunFoward状态;isShoot控制是否跳入Shoot状态。
Damaged Layer
先设置一下Damaged Layer的属性,通常需要设置的是Weight和Blending。Weight决定该层级动画占多少权重和Blending决定和其它层动画混合模式。Blending通常可以选择override(覆盖,覆盖上一层级的动画)和additive(添加,和上一层级动画进行融合)。根据我们的需求,可以设置为Weight为0.7,Blending为additive。
两种状态,受伤Damage以及正常状态(可以用Null表示)。右键新建一个空状态为Null作为默认的状态,然后再把Hurt动画拖入。
先分析一下需求。这里和Base Layer最大不同在于,Hurt动画触发播放完就结束了。不会再有过渡控制回到Null,因为回到Null状态不是我们控制的,而是动画是否播放完毕。
创建过渡:
- Hurt之后要连接到Exit状态,会自动回到Entry状态的,不用担心动画不会再触发(如果是子状态机的话,就是六边形符号里面的动画状态机Exit是退出了子状态机)
- Null过渡到Hurt
添加Parameter进行过渡控制。整个状态机中,Null到Hurt只会触发一次,所以创建一个trigger类型的onHurt变量控制就行。trigger和bool的区别在于,trigger触发是一次性事件触发,触发完立马回到未触发状态,而bool需要手动切换。
添加Animator
给HovertBot敌人挂载上Animator组件。然后把HoverBot_AnimatorController拖入到Animator的AnimatorController中。记得,挂载的是在Mesh模型那一级,不然没法绑定上网格。
代码控制
这里动画控制的逻辑不是很复杂,就放到Enemy Controller和EnemyWeaponController代码中了。但如果动画控制比较复杂,为了项目更好管理,会单独新建一个Script。
添加Animator变量
[Header("动画")]
public Animator anim;
由于Animator是在Controller挂载的代码下面一级的网格中挂载的,所以要用代码获取一下Animator。Controller代码挂载在Enemy_HoverBot,但是Animator组件挂载在HoverBotMesh中,因为Animator使用了骨骼动画依附于骨骼。在Awake或者Start代码部分加入下面代码,获取Animator。
anim = this.GetComponentInChildren<Animator>();
animator的控制主要依附控制前面设计三个Parameter,来完成动画之间的过渡。通常控制的函数有SetFloat、SetInteger、SetBool和SetTrigger,根据变量类型,在有需要的地方使用就好了。
效果
动画状态随着代码控制Parameter进行了切换,并且敌人做出了不同动画。