我怎样才能等待动画完成然后让代码恢复?

Posted

技术标签:

【中文标题】我怎样才能等待动画完成然后让代码恢复?【英文标题】:How can I wait for the animation to finish then let the code resume? 【发布时间】:2022-01-19 20:19:07 【问题描述】:

我试图让敌人攻击玩家并通过动画攻击敌人,但是当其他人处于活动状态时我必须阻止动画开始的方法不起作用。问题是我的方法不起作用。更具体地说,它基本上不像评论那样做任何事情。如果您需要任何代码,我应该能够提供。

代码如下:

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); ? 【参考方案1】:

我认为您的第一种方法在理论上可行。唯一的“问题”是,即使您已经在动画组件中设置了标志,动画制作器也是帧内最后执行的操作之一(请参阅Execution Order of Events)。所以我认为你只需要给它时间来实际切换状态。

你可以例如在开始等待当前状态的长度之前尝试先使用yield return new WaitForEndOfFrame ();


另一种方法可能是Animator Events。您可以在动画的最后放置一个事件,然后简单地让它调用一个专用方法。

【讨论】:

以上是关于我怎样才能等待动画完成然后让代码恢复?的主要内容,如果未能解决你的问题,请参考以下文章

让 Jquery 函数等待动画完成

我怎样才能让我的程序等待输入,而不是在循环中

JavaFX 在转到下一个方法之前等待动画方法完成

创建执行动画的等待队列

js运行时间比较长,怎么才能在它运行之前页面置灰并且有请等待的提示

Invoke-sqlcmd 等待恢复完成,然后再进行下一个任务