如何等待动画完成后让代码继续执行?

5
我正在尝试让敌人通过动画攻击玩家,但是我现在的方法无法防止当其他动画正在播放时该动画开始执行。问题在于这个方法根本不起作用。更具体地说,它基本上像一条注释一样什么都不做。如果需要代码,请告诉我。
以下是代码:
IEnumerator PlayAnim(Animator anim, string booleanName) 
    {
        anim.SetBool(booleanName, true);
        yield return new WaitForSeconds(anim.GetCurrentAnimatorStateInfo(0).length + anim.GetCurrentAnimatorStateInfo(0).normalizedTime); // I checked and got a value for that number so it should be paused
        anim.SetBool(booleanName, false);
        
    }

在上面的代码中,我在开头和结尾处放置了一个调试语句,当我运行代码时,它们在同一秒内运行,因此我知道它不起作用。
以下是它的调用方式:
public void AttackPlayer(GameObject playerPos, Animator anim, NavMeshAgent agent, GameObject self, bool MultiAttack, float inRange, float inView, float AttackRange, bool isBlocking, bool HasSeenPLayer)
    {       

        if (MultiAttack)
        {                      
            MultAttack(playerPos, anim, agent, self, inRange, inView);                    
        }
        else
        {
            anim.SetBool("Attack2", false);
            anim.SetBool("Attack3", false);
            StartCoroutine(PlayAnim(anim, "Attack"));
        }
        
        if (!PlayerPos.FindPlayerPos(AttackRange, playerPos.transform, inView, self, HasSeenPLayer))
        {
            anim.SetBool("Attack", false);
            anim.SetBool("Attack2", false);
            anim.SetBool("Attack3", false);
            state = State.Chase;
        }
    }

    public void MultAttack(GameObject playerPos, Animator anim, NavMeshAgent agent, GameObject self, float inRange, float inView)
    {
        
        if (random == 0) random = Random.Range(1, 5);

        if (random == 1)
        {            
            StartCoroutine(PlayAnim(anim, "Attack"));
            random = 0;
            
            return;
        }

        if (random == 2)
        {
            if (HasParameter("Attack2", anim))
            {                
                StartCoroutine(PlayAnim(anim, "Attack2"));
                random = 0;
                
                return;
            }
            
            StartCoroutine(PlayAnim(anim, "Attack"));
            random = 0;
            
            return;
        }

        if (random == 3)
        {            
            if (alk != null)
            {                  
                alk.particle.gameObject.SetActive(true);
                alk.particle.Play();                
            }
                        
            StartCoroutine(AlkAnim(anim, "Attack3"));
            random = 0;
            
            return;
        }

        if (random == 4)
        {            
            BlockPlayer(playerPos, anim, agent, inRange, inView, self);
            random = 0;
            
            return;
        }

        
        StartCoroutine(PlayAnim(anim, "Attack"));
        random = 0;
        
        return;

    }

    IEnumerator AlkAnim(Animator anim, string booleanName)
    {
        anim.SetBool(booleanName, true);
        yield return new WaitForSeconds(anim.GetCurrentAnimatorStateInfo(0).length + anim.GetCurrentAnimatorStateInfo(0).normalizedTime);
        anim.SetBool(booleanName, false);
        if (alk != null)
        {
            alk.particle.Stop();
            alk.particle.gameObject.SetActive(false);
            random = 0;
        }
    }

    public static bool HasParameter(string paramName, Animator animator)
    {
        foreach (AnimatorControllerParameter param in animator.parameters)
        {
            if (param.name == paramName)
                return true;
        }
        return false;
    }    


void Start()
{
    StartCoroutine(GetGood());
}

 IEnumerator GetGood()
    {        
        TtF.ChoseChasingWhatStateToAttackPlayer(agent, Player_pos.player, self, anim, MultiAttack, inRange, inView, AttackRange, isBlocking, hasSeenPlayer);
        
        yield return new WaitForSeconds(0.5f); 
        StartCoroutine(GetGood());
    }

@derHugo 不好意思,您的意思是将其放置在这样的位置吗:yield return new WaitForEndOfFrame(); yield return new WaitForSeconds(anim.GetCurrentAnimatorStateInfo(0).length + anim.GetCurrentAnimatorStateInfo(0).normalizedTime); - Arnice123
1个回答

1
我认为你的第一种方法理论上是可行的。唯一的 "问题" 是,即使你已经在动画组件中设置了标志,动画器仍然是在帧内执行的最后一件事(请参见 执行事件的顺序)。所以我认为你只需要给它一些时间来实际切换状态。
例如,你可以尝试先使用 yield return new WaitForEndOfFrame ();,然后开始等待当前状态的长度。
另一种方法是使用动画事件。你可以在动画的最后放置一个事件,并简单地让它调用一个专用方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接