How do I stop an automatically repeating Coroutine?
I am using a coroutine to remind the player that when the Furnace is Idle it is wasting Gas, but it seems that calling a 'StopCoroutine()' does not exactly force the coroutine to stop in it's tracks, it seems to allow it to finish before stopping (which if this coroutine is allowed to continue to it's finishing point it will automatically start itself again), which in this case I need it to STOP no matter what, I do not wish for it to finish it's last call as this continually notifies the player that the Furnace is Wasting gas even though they have already done the steps to stop the Notification from appearing, the reason I am doing it like this is I do not wish to have yet another timer in Update() that repeatedly starts the Coroutine every 60 seconds. Is there another method that can be called that actually does 'Stop' the coroutine without allowing it to finish?
I also had this same issue with a separate case when the Player clicks an object the First coroutine is Started that moves the Tool from the Players Hand to the Selected Object to Dismantle said object, once that is completed, it then starts a another coroutine that moves the Tool back from the Object Position to the Players Hand, though I wanted the Player to be able to interrupt the Tool moving back to the Player and instead stop it at its current position and start moving from its stops position to the next clicked Object to Disassemble, this is where the problem started was the Interruption ('StopCoroutine()' call) did not actually stop the coroutine and both Coroutines were fighting one another, one to move the Tool back to the Player and one trying to move the Tool to the next selected object, which both were never successful and could never finish their task. This worked flawlessly if I gave the coroutine time to finish, though there seems to be no way to physically interrupt/cancel a coroutine.
Below is the code being used for the Furnace Notification case (if solved I will be able to also fix the Tool Positioning coroutines with the same process):
IEnumerator presentIdleNotif()
{
notif.customErrorPopup("Furnace is Idle and is using Gas!",
"The Furnace has Finished melting it's Raw Metal - " +
"Gas is still being consumed - " +
"You should either extinguish the Furnace or continue Melting more Materials to save wasting Gas - " +
"You can disabed this '60 second' recurring Notification by Opening the Furnace Panel or Opening the Furnace Lid." +
"", 0, 5);
yield return new WaitForSeconds(60);
StartCoroutine(presentIdleNotif());
}
public void openPanelFurnace()
{
StopCoroutine(presentIdleNotif());
furnacePanel.SetActive(true);
refer.pcInt.charIsInteracting(true);
isPanelOpen = true;
}
public void openFurnace()
{
StopCoroutine(presentIdleNotif());
anim.SetBool("isOpen", true);
anim.SetBool("isClosed", false);
isOpen = true;
}
public void makeMolten()
{
if (!isMolten)
{
if (containsAlum || containsBrass || containsCopper || containsIron)
{
if (!furnacePanel.activeInHierarchy)
{
StartCoroutine(presentIdleNotif());
}
fullCrucImage.enabled = false;
moltenCrucImage.enabled = true;
crucNotifText.text = "Metal is now Molten!";
crucNotifText.color = Color.white;
isMolten = true;
}
}
}
These are just the Functions that handle the Coroutines, any help would be greatly appreciated! :)
I do understand that the problem lies with the coroutine automatically restarting itself after the 60s timer, though the question is, is there a better way to do this? or is there a function that actually 'STOPS' the coroutine and does not allow it to past go, does not collect $200... it stops right there in its tracks.
Answer by andrew-lukasik · Jul 14, 2021 at 06:47 AM
First things first, behold, a looped coroutine:
IEnumerator MyCoroutine ()
{
var wait = new WaitForSeconds( 1 );
while( true )
{
yield return wait;
Debug.Log("tick");
}
}
Then, to stop it, you have two choices. This:
Coroutine _coroutine = null;
void Start ()
{
_coroutine = StartCoroutine( MyCoroutine() );
}
public void Staph ()
{
StopCoroutine( _coroutine );
}
Or this:
public void Staph ()
{
StopCoroutine( nameof(MyCoroutine) );
}
Thank you for that I will give it a go! :) Could you explain the difference between calling 'StopCoroutine(MyCoroutine())' and 'StopCoroutine(nameof(MyCoroutine))' what is the difference between the two and why does the first one not actually stop the coroutine?
Also in your first piece of code what does the while(true) refer to? Does it mean: while 'The coroutine has been started but not yet stopped' then do this function, otherwise do nothing?
StopCoroutine( MyCoroutine() )
starts a new coroutine and then stops it immediately - which is not what you want. You want to stop existing coroutine and this is whereStopCoroutine( _coroutine );
comes in, where you refer to a specific object representing a running coroutine.StopCoroutine( nameof(MyCoroutine) )
&StopCoroutine( "MyCoroutine" )
just stops a coroutine by namewhile(true) { /*code*/ }
is a classic infinite loop. Be aware that excluding thatyield return wait;
from the code executed inside that loop will freeze your program (editor/build)
I came on here to see if I could help, and ended up learning something new instead! Thankyou <3
Your answer
Follow this Question
Related Questions
Add points every five seconds 1 Answer
Coroutine cancels for no reason 0 Answers
Coroutine Not working properly. 1 Answer
Why isn't my coroutine working when I call it from another script. 0 Answers