- Home /
Cancel IEnumerator in progress
I have a script that I'm trying to use to track when a player goes out of the map's bounds. If the player doesn't get back in bounds in ten seconds his unit is destroyed. The script works when the player goes out of bounds, but the IEnumerator doesn't stop when he returns to the map.
The bounds is just a box trigger, when the player exits it starts the coroutine, and when he enters I need it to stop the coroutine. Thank you.
void OnTriggerEnter (Collider other) {
GameObject go = other.gameObject;
if(go.transform.root.gameObject.CompareTag("Player")){
status = go.transform.root.gameObject.GetComponent<NetPlayer>();
status.outOfBounds = false;
}
}
void OnTriggerExit (Collider other) {
GameObject go = other.gameObject;
if(go.transform.root.gameObject.CompareTag("Player")){
status = go.transform.root.gameObject.GetComponent<NetPlayer>();
status.outOfBounds = true;
StartCoroutine(OutOfBounds(10));
}
}
IEnumerator OutOfBounds(float secs){ float cd = secs; while(status.outOfBounds == true){ while(cd > 0){ yield return new WaitForSeconds (1); GameObject.Find("MessageText").gameObject.GetComponent<GUIText>().text = "You are leaving the battle.\nReturn to battle or be destroyed.\n" + cd ; cd --; } GameObject.Find("MessageText").gameObject.GetComponent<GUIText>().text = ""; yield return new WaitForSeconds (.2F); status.hullHealth = 0; } }
Answer by skovacs1 · Sep 23, 2010 at 02:50 PM
It's not an IEnumerator. The IEnumerator is the return type of the co-routine. You want to stop the coroutine.
You have the co-routine that does the following:
IEnumerator OutOfBounds(float secs){
float cd = secs;
//Loop conditionals are checked at the end of each iteration.
//Is there a point in having this?
//Are you going to kill them multiple times when you don't set outOfBounds = false?
while(status.outOfBounds == true){
//Wait secs seconds, posting the message every second
while(cd > 0){
yield return new WaitForSeconds (1);
GameObject.Find("MessageText").gameObject.GetComponent<GUIText>().text =
"You are leaving the battle.\nReturn to battle or be destroyed.\n" + cd ;
cd --;
}
GameObject.Find("MessageText").gameObject.GetComponent<GUIText>().text = "";
//Wait .2 seconds and then kill them
yield return new WaitForSeconds (.2F);
status.hullHealth = 0;
}
}
Your co-routine has nothing to stop it until it kills the character and a loop that can do it multiple times. Try to understand what your code is doing as this lack of understanding is the cause of most difficulties.
To do what you're describing, try doing something like:
IEnumerator OutOfBounds(float secs){
float cd = secs;
while(cd > 0) { //Check over secs seconds
if(!status.outOfBounds) break; //If we're back in bounds, we're done
yield return new WaitForSeconds (1);
GameObject.Find("MessageText").gameObject.GetComponent<GUIText>().text =
"You are leaving the battle.\nReturn to battle or be destroyed.\n" + cd ;
cd --;
}
GameObject.Find("MessageText").gameObject.GetComponent<GUIText>().text = "";
if(status.outOfBounds) { //We're still out of bounds after secs seconds
yield return new WaitForSeconds (.2F);
status.hullHealth = 0;
}
}
Thank you. All I needed was the break statement. The way the rest of my project is structured it will only kill him once, not multiple times.
Then why do you have that while loop while(status.outOfBounds == true) if you're only doing one iteration of the loop?
Answer by Eric5h5 · Sep 23, 2010 at 03:14 PM
You can use StopCoroutine to cancel an existing coroutine, but it must be started using the string version.
This totally is what I needed! Was using a trigger with a delay to change scenes if you stayed in for 5 seconds, but when he exited the trigger it wouldn't cancel the task, it would still change scenes.
I had written it :
StartCoroutine (delayTask());
and not
StartCoroutine ("delayTask");
This is actually outdated. In the past you could only stop coroutines which were started using a string. In the recent Unity versions they added overloads for StopCoroutine which takes either the IEnumerator instance that was used to start the coroutine, or the Coroutine object that is returned by StartCoroutine. In most cases the simplest solution is to store the Coroutine object in a variable
Coroutine co;
// [ ... ]
co = StartCoroutine(delayTask());
// [ ... ]
StopCoroutine(co);
This is much better for refactoring (since the name of the method isn't inside a string) and is also faster.
Your answer
![](https://koobas.hobune.stream/wayback/20220613073729im_/https://answers.unity.com/themes/thub/images/avi.jpg)