In Unity3D, this is my code:
void ActivateBuff1(){
gun.equippedGun.msPerShot /= 2;
gun.equippedGun.shotsLeftInMag += 10;
StartCoroutine (WaitRage ());
}
void ActivateBuff2(){
player.speedModifier *= 1.5f;
StartCoroutine (WaitSpeed ());
}
IEnumerator WaitRage(){
yield return new WaitForSeconds(powerUpDuration);
gun.equippedGun.msPerShot *= 2;
}
IEnumerator WaitSpeed(){
yield return new WaitForSeconds(powerUpDuration);
player.speedModifier /= 1.5f;
}
Everytime a player run into a power up one of the ActivateBuff Methods gets called. Obviously powerUps effects don't last forever though so I used IEnumerators
to reverse the effects of my original method after the wait for a certain number of seconds. For some reason though, the code within the IEnumerators
never gets called. Please help...(and please suggest an alternative way of coding this perhaps as I know it isn't very clean)
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 : : : : : :..................................:.....................:...............:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With