- Home /
If you disable a gameobject, does an InvokeRepeating loop end or pause?
If you have a gameobject with a script running a current InvokeRepeating method and you set the gameobject to inactive, then back to to active, will the InvokeRepeating loop resume or will it have been cancelled outright?
By the way, to cancel an InvokeRepeating("someName" .) is very simple,
just use CancelInvoke("someName");
Answer by robertbu · May 18, 2013 at 06:16 AM
The answer is that the object will continue to execute the InvokeRepeating().
Deactivating a game object does not stop the InvokeRepeating().
To deactivate the whole game object: gameObject.SetActive(false)
Deactiving just the script component itself does not stop the InvokeRepeating().
to deactivate just the script component: this.enabled = false
BUT NOTE THAT COROUTINES ARE DIFFERENT
Note however that ordinary coroutines, do indeed get stopped, when you deactivate the game object. However if you deactivate only script itself then the coroutine does keep going.
For InvokeRepeating...
1) disable whole game object - InvokeRepeating does not stop
2) disable just the script component - InvokeRepeating does not stop
For coroutines...
3) disable whole game object - coroutine DOES stop
4) disable just the script component - coroutine does not stop
In all four cases, the repeat is "eliminated", it is NOT paused. If you again SetActive(true), in all four cases, the repeat does NOT continue where it left off.
.
When I have questions like this one, I just test it:
private var i = 0;
function Start() {
InvokeRepeating("CountUp", 0.0, 0.5);
Invoke("Disable", 3.0);
}
function Disable() {
gameObject.SetActive(false);
}
function CountUp() {
i = i+1;
Debug.Log("i=" + i);
}
to test all four situations, simply do this,
using UnityEngine;
using System.Collections;
public class CoTeste:MonoBehaviour
{
void Start ()
{
InvokeRepeating("_everySecondInvoked", 1.1f, 1.1f);
StartCoroutine(_everySecondCoroutine());
}
private void _everySecondInvoked()
{
Debug.Log("this I.R. appears every second "
+ Random.Range(1111111,9999999) );
}
private IEnumerator _everySecondCoroutine()
{
while(true)
{
Debug.Log("\t\t\t\tthis coroutine appears every second "
+ Random.Range(1111111,9999999) );
yield return new WaitForSeconds(Random.Range(1.1f,1.2f));
}
yield break;
}
}
Run the project, and simply in the editor try disabling just the script (un-tick the box in the inspector).
note that both the coroutine and the invokeRepating simply keep going forever.
Start over, and disable the whole game object (un-tick the box in the inspector).
note that the InvokeRepeating keeps going forever, BUT, the coroutine DOES STOP.
Simply use OnDisable()...
, or one of the similar routines, if you want something "custom" to happen when a game object (or just the script) is disabled.
OnDisable and the similar routines
This is completely commonplace. Indeed,
... You almost always use OnDisable() ... .
when you launch a coroutine or invokeRepeating - unless it's a really trivial situation and it doesn't matter.
But scripts stop running when de-activating an object, correct? So how is InvokeRepeating still running?
And you're right, this is testable. I usually google a question first and will post it as a question if it doesn't already exist, presu$$anonymous$$g it might save others time in the future! :)
Hi Essential - I think ultimately there's no "real" explanation for the difference between the four situations. It's really not worth worrying about. It's completely and totally normal in software broadly, that if you launch "some sort of process" (another thread, scene - whatever) then, naturally, that process is not particularly killed when the launcher process is killed. Again it's honestly not worth worrying about why Unity adopted, basically, the system of four points shown above.
If you want to make a situation where (say) invokes or coroutines are indeed killed when you kill the "launcher", that is trivial to do so (just use OnDisable, etc, with a line of code. Note that if Unity worked the "other" way in any of the four situations, and you needed it to work the 'other" way, again you'd just have to set that up yourself. (It can't "always work for everyone", they had to pick one way or the other.)
The bottom line is "everyone" who programs unity just has to know it works as per the four routes above - it's no big deal.
Why is the text in this so absurdly huge? Can an ad$$anonymous$$ please fix this. No reason to put everything in giant bold lettering.
Answer by GingerLoaf · Mar 17, 2015 at 07:12 PM
This post is very old at this point, however I had some interesting thoughts that I wanted to share on this subject for any future viewers.
always like to think about the enabled property of a component as something closer to "allowUnityLifeCycleEvents" rather than enabled. An interesting example outside of the coroutine or invokerepeat case would be the case where I have (enabled) scriptA that references a disabled scriptB reference. ScriptA can invoke public facing members of scriptB despite the fact that scriptB is disabled. "Enabled" does not mean "nothing will function and everything gracefully pauses".. instead it only stops the built in unity lifecycle events from being triggered (Awake, Start, Update, LateUpdate, ect...). A good test/sandbox could be this:
public class TestClassA : MonoBehaviour {
private TestClassB m_classBReference = null; public void Update() { m_classBReference.Update(); } } public class TestClassB : MonoBehaviour { public void Update() { Debug.Log("I am active!"); } }
Create a new scene, create a gameobject and place a "TestClassA" component on it
Create another gameobject and place a "TestClassB" component on it
Drag and drop the gameobject with your "TestClassB" component on it onto the "Class B Reference" property exposed in the inspector for the gameobject with the TestClassA component
Run the scene
You should see the logs being printed out at first... now try disabling combinations of both scripts. If you disable TestClassB and leave TestClassA enabled, you should still see the logs. Play around with this and become comfortable with how it works.
Now in regard to the "I think my script should disable everything" mentality... Unity will not do this for you, but you have powerful tools and frameworks at your fingertips to accomplish something that you are comfortable with. You could create your own class to use instead of MonoBehaviour (pardon my awful programmer class name) named something like "DisableableBehaviour". This class can inherit from MonoBehaviour... then all you need to do is framework how you want it to work... for example: You could expose your own special function for starting coroutines or invokerepeat calls and have the class track them so that the class can cancel them on disable and restart them on enable. I'm certain there are tons of ways of doing this... just know that unity doesn't need to do it all. Coroutines and invoke calls are very useful in the fact that they do span across frames regardless of enable or disable states, but you can always code up something that works for you :)
Hi Ginger. Simply use "OnDisable" if you want something to happen when the gameObject, or, script is disabled. This is an utterly commonplace aspect of program$$anonymous$$g. (It's exactly like when you do cleanup along the lines of "when I am destroyed..." in any environent.) It' trivial, easy, and commonplace.
note again that
actual coroutines DO IN FACT GET STOPPED if you disable the WHOLE game object.
.
But generally - who can remember that 'exception' - just use "OnDisable" to do whatever you want when, well, the thing is disabled. It's one line of code.
Answer by nitsnbolts_unity · Dec 18, 2020 at 05:38 AM
Not sure if this was an option in Unity when this was posted - but using Cancellnvoke() on any Monobehaviour script stops all invoke calls https://docs.unity3d.com/ScriptReference/MonoBehaviour.CancelInvoke.html