今天做一个FPS游戏的时候,用的是新版的动画系统,遇到一个问题。
就是用枪打敌人的时候,敌人会播放一个被击中的动画,但是如果在动画播放的过程中再射击敌人,敌人会先把第一个被击中的动画播放完,才再播放第二个被击中的动画。而且被击中后还原为正常形态也有点慢。
这样被枪打中的打击感就没有了,降低了FPS游戏的体验。
我理想中的效果是,当我用枪击中敌人,敌人播放被击中的动画,当我再开第二枪的时候,敌人能够停止第一枪的正在播放的被击中动画,重新开始播放被击中动画。如果我连续射中敌人,敌人就会有一个不断被击中的鬼畜的效果。
解决方案
思路:
我在动画状态机里面再创建一个一模一样的受伤的状态hurt2,然后设置一个伴随被击中次数不断累加的整型变量,当变量为单数时切换受伤状态1,变量为双数时切换受伤状态2,这就实现了立刻停止当前动画并重新开始播放动画的效果。而动画切换有点慢的话,可以不勾选状态和状态之间切换时的Transition的Has Exit Time,这样就不会有动画和动画之间过渡的那个的时间。如果一个动画有Conditions建议取消Has Exit Time,不然会出现无法及时触发的问题。Has Exit Time就是必须过度的时间,处于这个时间时,是不允许任何对动画的操作的。
动画状态机配置:
两个受伤动画之间过渡的Transition和walk与两个受伤动画之间的Transition配置:
当我们击中敌人时,调用敌人节点下的Enemy脚本里面的hurt函数:
public void hurt()
{
a++;
Debug.Log("打到怪物:"+a);
if (a % 2 != 0)
{
this.anim.SetInteger("anim_state", 1);//播放hurt动画
}
else if (a % 2 == 0)
{
this.anim.SetInteger("anim_state", 2);//播放hurt2动画
}
if (a >= 10)//怪物死亡,切换到3,播放死亡动画
{
this.anim.SetInteger("anim_state", 3);
}
}
敌人节点下的Enemy脚本里面的Update函数:
void Update () {
AnimatorStateInfo info = anim.GetCurrentAnimatorStateInfo(0);
// 判断动画是否播放完成
if ((info.normalizedTime >= 1.0f && info.IsName("Base Layer.hurt")) || (info.normalizedTime >= 1.0f && info.IsName("Base Layer.hurt2")))
{
this.anim.SetInteger("anim_state", 0);//设置参数anim_state的值为0,我们之前也设置了当它等于0的时候会跳转
}
// 判断死亡动画是否播放完成
if (info.normalizedTime >= 1.0f && info.IsName("Base Layer.die"))
{
this.box.enabled = false;
this.anim.Stop();
MonoBehaviour.Destroy(this.gameObject);
a = 0;
Debug.Log("删除怪物");
}
}