今天做一个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("删除怪物"); } }