Do not know how to use coroutines in Unity3D

前端 未结 3 642
被撕碎了的回忆
被撕碎了的回忆 2021-02-14 16:28

In Unity3D, this is my code:

void ActivateBuff1(){
    gun.equippedGun.msPerShot /= 2;
    gun.equippedGun.shotsLeftInMag += 10;
    StartCoroutine (WaitRage ())         


        
3条回答
  •  有刺的猬
    2021-02-14 16:49

    Under normal circumstances, the code you've supplied should work fine. However, as determined in the comments, there's a caveat - if the Gameobject calling the coroutine is disabled/destroyed before the delay from WaitForSeconds() has completed, the coroutine will be stopped and the remaining code won't be called at all. You will either need to wait for the coroutine to finish before destroying the Gameobject, or have some other Gameobject call the coroutine.

    You mentioned that you were also looking for alternatives that might simplify your code - you might consider Invoke(), which lets you call a method after a specified delay. (As long as you're not triggering this very often, the overhead from reflection won't have an appreciable effect on your performance.) So your code could be rewritten to be somewhat shorter:

    void ActivateBuff1(){
        gun.equippedGun.msPerShot /= 2;
        gun.equippedGun.shotsLeftInMag += 10;
        Invoke("ResetPlayerRage", powerUpDuration);
    }
    
    void ActivateBuff2(){
        player.speedModifier *= 1.5f;
        Invoke("ResetPlayerSpeed", powerUpDuration);
    }
    
    void ResetPlayerRage(){
        gun.equippedGun.msPerShot *= 2;
    }
    
    void ResetPlayerSpeed(){
        player.speedModifier /= 1.5f;
    }
    

    Unfortunately, Invoke() will also be cancelled if the Gameobject is destroyed - but unlike a coroutine, it won't be cancelled if the Gameobject is disabled. So you could disable the Gameobject first (so it becomes invisible and doesn't interact with anything), then destroy it only after running the delayed method:

    void ActivateBuff1(){
        gun.equippedGun.msPerShot /= 2;
        gun.equippedGun.shotsLeftInMag += 10;
        gameObject.SetActive(false);
        Invoke("ResetPlayerRage", powerUpDuration);
    }
    
    void ResetPlayerRage(){
        gun.equippedGun.msPerShot *= 2;
        Destroy(gameObject);
    }
    

    Here's a summary of whether Invoke() and coroutines will be stopped depending on how you manipulate the script component or entire Gameobject:

    ..........................................................................
    :                                  :                     :               :
    :          Does it stop?           :   InvokeRepeating   :   Coroutine   :
    :                                  :                     :               :
    :..................................:.....................:...............:
    :                                  :                     :               :
    :   Disable the script component   :         No          :      No       :
    :                                  :                     :               :
    :..................................:.....................:...............:
    :                                  :                     :               :
    :   Destroy the script component   :         Yes         :      Yes      :
    :                                  :                     :               :
    :..................................:.....................:...............:
    :                                  :                     :               :
    :   Disable the game object        :         No          :      Yes      :
    :                                  :                     :               :
    :..................................:.....................:...............:
    :                                  :                     :               :
    :   Destroy the game object        :         Yes         :      Yes      :
    :                                  :                     :               :
    :..................................:.....................:...............:
    

提交回复
热议问题