unity技术日志之十五秘密潜入:敌人初始设定和敌人动画控制器
1、敌人初始设定 现在将给游戏添加巡逻守卫。 详情:每个守卫都会有默认的巡逻路线,如果守卫看到了玩家或听到了玩家的脚本声,或是玩家触发了警报器,或是被其他守卫发现时,他们会跑向最后发现玩家的位置,或是玩家触发警报器的位置。当守卫看到玩家时,会向玩家射击。游戏中有两个变量存储玩家的位置,一个是全局变量,会发送给所有守卫。还有一个是私有变量,发送给指定的守卫。当玩家触发警报系统或被守卫发现时,全局变量将发生变化。当守卫听到玩家跑步的脚步声或当玩家通过喊叫吸引守卫注意时,只有私有变量发生变化。如果全局变量没有被重置(玩家被发现时),守卫各自的私有变量将等于全局变量,并聚集在全局变量位置。守卫将含有两个碰撞器,一个大的“Sphere Collider”作为触发器,还有一个“Capsule Collider”,球形触发器的范围作为守卫的视觉和听觉范围,“Capsule”碰撞器用于普通的碰撞。因为守卫与碰撞器一起移动,所以还需添加刚体组件。刚体将勾选“Is Kinematic”,因为守卫将不会对碰撞做出反应,且移动指令将由“Nav Mesh”决定,所以守卫还将包含“Nav Mesh Agent”组件,这个组件将以物理方式让守卫移动,并把信息传递给动画控制器,从而决定守卫应播放哪种动画,守卫将使用5个脚本,其中4个将添加在守卫中,另一个为辅助类。 “EnemySight”脚本:设定守卫的视听范围,用于检测玩家是否进入球形触发器范围。 “AnimatorSetup”脚本(辅助):不会作为组件添加在守卫中,将把“EnemyAnimation”脚本中的信息传递到动画控制器中。它会从“Nav Mesh Agent”读取速度方向。 ”EnemyAI“脚本:守卫的大脑,根据玩家是否被发现而控制守卫的行为,然后把信息传递给”Nav Mesh Agent“组件,决定守卫应该做什么。 ”EnemyShooting”脚本:控制守卫射击玩家时的动作,包括射击伤害和射击频率。 把守卫模型拖入到场景,“Models”-》“char_robotGuard”拖入到场景中,”Position“(-18,0,6.5)。展开,选中“char_robotGuard_body”和“char_robotGuard_skeleton-》char_robotGuard_Hips-》char_robotGuard_Spine-》char_robotGuard_Neck-》char_robotGuard_Head-》char_robotGuard_helmet”,勾选”Use Light Probes“,这样守卫模型被动态照亮了再把它的“Tag”指定为“Enemy”。 因为模型在导入时设置了“Rig”,所以“Animator”组件会自动添加。添加“Sphere Collider”中心点为守卫模型的中心点,“Center Y”设为1,“Radius”设为10,勾选“Is Trigger”。

下一步在子对象“char_robotGuard_body”中添加“Capsule Collider”,“Center X\Z”都为0,“Center Y”设为1,“Radius”为0.3,“Height”为2。

其他组件添加到父对象中,由于碰撞器也将移动,所以添加刚体组件“Rigidbody”,勾选“Is Kinematic”,这样守卫不会在碰撞后被弹开,不勾选“Use Gravity”。

再添加“Nav Mesh Agent”组件,组件的默认值大部分不用修改,”Add Component-》Navigation-》Nav Mesh Agent“,”Stopping Distance”设为0.8,

现在可以烘焙“Nav Mesh”了,需要烘焙对象标记为“Navigation Static”,之前烘焙光照贴图时标记为“Static”的对象也将自动标记“Navigation Static”。 首先展开“env_stealth_static”,检查“debris”,“ground”,“liftshaft”,“props”,还有两个“walls”,还要检查“battleBus”和“prop_switchUnit”,都勾选“Navigation Static”。

打开菜单“Window-》Navigation”,在“Bake”标签下,把“Radius”设为0.3,让守卫可以穿过更狭窄的空间。“Height”设为1(如果这个值太低,“Nav Mesh”将穿过物体下方,比如巴士底部,会让守卫巡逻时穿过巴士),点击“Bake”按钮烘焙。

2、敌人动画控制器 守卫的动画是由“Nav Mesh Agent”组件的速率控制,这是Unity内置的AI功能。 选中“Animator”文件夹,点击“Create-》Animator Controller”,命名为“EnemyAnimator”,打开“Animator”视窗,添加4个“float”参数。都为“Float”,分别命名为“AngularSpeed”(敌人的转向速度),“Speed”(敌人的移动速度),“Shot”(射击动画曲线的一个参数),“AimWeight”(决定“IK”覆盖动画的比重)。最后添加一个“bool”参数“PlayerInSight”(判断敌人是否发现玩家)。

敌人的全部动画将在储存在一个“2D Blend Tree”中,在右键菜单中选择“Create State-》From New Blend Tree”,在“Inspector”中命名为“Locomotion”,双击它进行编辑,同样命名为“Locomotion”,“Blend Type”选择“2D Freefrom Cartesian”(便于设置“Speed”和“AngularSpeed”),下一步选择两个轴代表的参数,X轴代表“AngularSpeed” Y轴代表“Speed”,这样地图动画就体现为:左方向为向左转,右方向为向右转,上方向为跑步,下方向为走路或站立。

下一步添加所有将要使用的动作,首先添加”turnOnSpot“动画,打开”Animators“目录下的”Humanoid“文件夹,找到”humanoid_turnOnSpot“和”humanoid_idle“,在”humanoid_turnOnSpot“中找到”TurnOnSpotLeftA-D“(从A到D),还有”TrunOnSpotRightA-D“。在”humanoid_idle“中找到”Idle“。选中”Locomotion Blend Tree“找到动作列表,点击加号选择”Add Motion Field“,分别把以上的动画拖入到”Motion“中

下一步,找到并展开4个包含”walkForward“字样的文件,添加相应的动画,添加顺序为”WalkLeftShort“,”WalkLeftMedium“,”WalkLeftWide“,“Walk”,“WalkRightShort”,“WalkRightMedium”,“WalkRightWide”。 最后添加含有“runForward”字样的文件中找到,添加“RunLeftMedium/Wide”,“Run”,“RunRightMedium/Wide” 下一步计算动画在2D平面上的位置,点击”Compute Position“的下拉菜单,选择”Speed And Angular Speed“,它会自动计算”Motion“的”Speed“和”AngularSpeed“阈值,阈值时根据Unity检测到的每个动画的”Root Motion“来计算的,这种计算阈值的方式适用于任何动画,无论参数是否在控制器中,这是”Blend Tree“中内置的,基于”Root Motion“的计算方式,我们把参数命名为”Speed“和”AngularSpeed“,因为它们与动作的计量一致。”AngularSpeed“是通过弧度计算的,而不是通过角度计算。弧度是另一种测量角度的方式,一整圈是360度,也就是2Π个弧度,所以转一圈大概是6.X个弧度,转半圈是3.X个弧度。所以左右最大转向幅度动画大概是2.5个弧度,也就接近为180度。


现在来预览下这些动作,把预览窗口调大一些。我们将使用守卫模型进行预览,而不是Unity内置的人物模型,把”Models“文件夹中的”char_robotGuard“拖入到预览窗口,点击播放。

敌人的动画控制器设置好了,接下来是位射击动画创建一个动画层,它的作用是即便敌人处于转向中,仍可以进行射击动作。 首先创建一个新动画层”Shooting“,下一步添加”Avatar Mask“,在”Animators“文件夹下创建”Avatar Mask“命名为”EnemyShootingMask“,展开”Humanoid“,只要禁用下半身就可以了。点击”Mask“后面的圆圈按钮,选择”EnemyShootingMask“。敌人射击时,手臂要指向玩家,这要通过”IK“实现,所以要勾选下面的”IK Pass“选项。

现在来设置动画层的状态,默认状态为空状态。右键菜单中选择”Create State-》Empty“(在正常状态下”Base“层的动画不会被覆盖),下一步创建”WeaponRaise“状态。打开”Humanoid“文件夹,找到”humanoid_weapon_raise“,展开后,把”WeaponRaise“拖入到”Animator“中。我们要让这个动作转换的迅速些,这样敌人才能在发现玩家后立刻射击,把”Speed“设为3。

要从空状态转换至”WeaponRaise“转换条件为”PlayerInSight=true“,右键点击”New State“选择”Make Transition“连接”WeaponRaise“,条件为”PlayerInSight=true“。

当举起武器后,要进行射击,所以要添加”WeaponShoot“动画,展开”human_weapon_shoot“把动画拖入到”Animator“视窗。现在要从”WeaponRaise“转换至”WeaponShoot“,条件为当“WeaponRaise”动画播放完毕后,所以使用默认条件,也就是“Exit Time”,右键点击”WeaponRaise“选择”Make Transition“连接”WeaponShoot“。 最后添加”WeaponLower“状态,展开”humanoid_weapon_lower“并拖入相应动画,从”WeaponShoot“转换至”WeaponLower“的条件是”PlayerInSight=false“。

最后,从”WeaponLower“转换至空状态。默认ExitTime。

最后,我们要确保敌人握着枪,再创建一个动画层。新建一个动画层,命名为”Gun“,在”Animators“文件夹中创建”Avatar Mask“,命名为”EnemyGunMask“。展开”Humanoid“,除了右手以外,其他全部禁用。跟之前操作一样。

这个动画层只需要一个手握枪的动画,在”Models“文件夹中,展开”char_robotGuard“找到”Gripped“,拖入到”Animator“视窗。注意”Blending“选项为”Override“,并且这个”Avatar Mask“只覆盖右手的动画,也就是说,敌人的右手在任何时候都是握着枪的。 敌人的动画控制器设置好了,把它拖入到敌人相应的组件中,选中”char_robotGuard“,把它拖入”Animator“组件中的”Controller“中。

-
[已注销] 赞了这篇日记 2015-08-06 03:08:26