- Home /
Yield Wait for Seconds (A little help here)
Alright so i have the code you can see below and what i want to happen is the enemy attacks the player once and the attack animation plays, then he waits for 10 seconds and then he attacks again and the animation plays again. However, with the below script he attacks all the time and the animation plays all the time too. Any suggestions? Notice that this is just a part of the code. That's why void Update(){ and other stuff is missing :P
if (readyforattack) {
if (!inRange ()) {
chase ();
} else {
StartCoroutine(attacking());
}
}
IEnumerator attacking(){
GetComponent<Animation> ().Play (attack.name);
yield return new WaitForSeconds (10);
GetComponent<Animation> ().Play (attack.name);
}
It can be in the other part of your code... If inRange is always true it will always attack for example.
It can also be the animation which is set to loop.
Well i just tried to set the animation to default and nothing. As for the inRange method it returns true only when the enemy is really close to the player for attacking.
How long does your attack animation take? Do you want a 10 sec delay after the attack animation, if so then add the animation time onto the 10.
Do this to add the delay onto the animation:
yield return new WaitForSeconds (10 + GetComponent<Animation>()[attack.name].time );
Oh i think I found it ^^
Just prevent the coroutine from being called multiple times with a bool like this:
if (readyforattack) {
if (!inRange ()) {
chase ();
} else if(!alreadyAttacking){
StartCoroutine(attacking());
}
}
IEnumerator attacking(){
alreadyAttacking = true;
GetComponent<Animation> ().Play (attack.name);
yield return new WaitForSeconds (10);
GetComponent<Animation> ().Play (attack.name);
alreadyAttacking = false;
}
Edit: hmm just like karl jones suggested actually.
By the way why 2 attacks? Shouldn't it be just one per Coroutine?
Answer by Tonks · May 18, 2015 at 05:11 PM
Just a tip, now that you have it working. Declare a WaitForSeconds in your private variables (private WaitForSeconds WFS;), then assign it as a new WaitForSeconds in your start function (WFS = new WaitForSeconds;), this way, you will save memory every time you call yield return new WaitForSeconds in your coroutine, as you can instead call the wait with yield return WFS (or whatever you called it) instead of instantiating a new WaitForSeconds each time.
A little memory optimisation tip for you :)
(Compare the two methods in the Unity Profiler if you want to know why this is a good idea)
Answer by Paul-Sinnett · May 18, 2015 at 04:31 PM
You are starting multiple instances of the coroutine, one new one every frame, while readyforattack is true. You could try setting readyforattack to false before starting the coroutine and back to true when the coroutine is finished.
if (readyforattack) {
if (!inRange ()) {
chase ();
} else {
readyforattack = false;
StartCoroutine(attacking());
}
}
}
IEnumerator attacking(){
GetComponent<Animation> ().Play (attack.name);
yield return new WaitForSeconds (10);
GetComponent<Animation> ().Play (attack.name);
readyforattack = true;
}