- Home /
What is the best between StartCoroutine or InvokeRepeating.
Hey Guys,
I'm wondering what is the best if I want to call a method every 0.5 seconds or even a smaller amount of time. I know I can do it with both StartCoroutine and InvokeRepeating but I wonder what are the advantages/inconveniences of both method and also performance wise, which is the best. Thanks a lot for your time and have a good day!
Claude
Answer by Owen-Reynolds · Jun 20, 2013 at 11:39 PM
InvokeRepeating is easier to learn and use, but, obviously, can only do things at regular intervals. Any weird multi-step, fade-wait-unfade stuff, you have to use a coroutine for (not because of a rule -- because there's no way to twist InvokeRepeat to do that stuff.) I'd say, anything you can use InvokeRepeating for, go ahead and do that.
I'd guess that InvokeRepeating is really just running StartCoroutine for you, with a free "every X seconds" delay. So it really makes no difference which you use.
"InvokeRepeating is easier to learn and use, but, obviously, can only do things at regular intervals"
does that mean this won't work if the damageSpeed changes its variable?
InvokeRepeating("Hit", damageSpeed, damageSpeed);
Because I'm having trouble with the repeating part. I have the invoke repeating triggered on a OnTriggerEnter, and it works once, or will only work and keep repeating if I force the two objects to stay within each others trigger.
I've made sure with the print function that the TriggerEnter/InvokeRepeating isn't being called multiple times and that it is the repeat part that triggers while the two objects are triggered.
Like all int/float parameters, values are "locked in" when you call the function. So a=2; InvokeRepeating(..., a); a=99;
grabs 2 as the permanent repeat time. The fact that it runs over time may fool you, but it still follows normal function rules.
Answer by chazzysb · Jun 03, 2015 at 03:04 PM
If you have 1 enemy shooting a bullet say every 5 seconds then you wont notice any difference between Invoke or StartCoroutine. However if you have say 30 enemies shooting complex bullet sequences every 5 seconds then Invoke & InvokeRepeating can have a huge effect on performance depending on the device its running on.
I would say always use StartCoroutine. ie.
// wait 3 seconds then shoot
Invoke("Shoot", 3f);
void Shoot() {
// shoot stuff
}
.. becomes ..
StartCoroutine("Shoot");
IEnumerator Shoot() {
yield return new WaitForSeconds(3f);
// shoot stuff
}
and
// wait 5 seconds then shoot every 2 seconds
InvokeRepeating("Shoot", 5f, 2f);
void Shoot() {
// shoot stuff
}
.. becomes ..
StartCoroutine("Shoot");
IEnumerator Shoot() {
yield return new WaitForSeconds(5f);
while (true) {
// shoot stuff
yield return new WaitForSeconds(2f);
}
}
Are you saying Invoke is slower? What device? "A huge effect" -- swapping 30 Invokes to identical StartCoroutines really sees a framerate change?
Had to revert code to check this again - In my bullet hell example, if I use Invoke to start a new method which in turn uses InvokeRepeat to fire 200 bullets in various patterns at a rate of 0.04 seconds between bullets, on around 20 enemies using this setup my FPS drops to 30 - 35. If I change this to use StartCoroutine then my FPS stays at around 55 - 58. This is on a mac i7. This issue is a lot worse when run on an iphone 6. I had to reduce the number of enemies to 15 - with using StartCoroutine I got an FPS of 28 - 30. If I change this to use Invoke and InvokeRepeating the FPS dropped right down to 3. Im saying InvokeRepeat can have a negative effect on FPS in this scenario. This is proof enough to me to always use StartCoroutine.
Wow, I didn't know you could use yield return that way in coroutines... I've just started learning program$$anonymous$$g, so, yeah, I'm a noob...
Anyways, in my mobile project I was using InvokeRepeating to deplete 4 stat meters/bars every some specified amount of time (similar to the sims), maybe I should change them to coroutines ins$$anonymous$$d? I also have some code that cancels the invoke and restarts it in case Update() detects the time float gVar changing (I'm using Adventure Creator which uses its own gVar system)... but I guess it would kind of be the same if I capture the data in a float variable which I can then pass to the coroutine? umm... or should I just capture it directly inside the coroutine ins$$anonymous$$d of update? (i'm guessing the second? although this way, if the time changes, there maybe a bit of a delay?)
This question is a piggyback, which we prefer you not do. Look at how specific this Q is -- StartCoroutine vs. InvokeRepeating. Try to break your Q into parts that small and look them up.
If you want to ask several Qs at once, or want help and comments on a project, start a new Q in the Forums or the HelpRoom area here (which isn't as regulated.) Thanks.
Thanks, You addressed performance which the accepted answer did not.
Answer by emongev · Sep 03, 2014 at 07:53 PM
I found this on a comment of a gamasutra article: "The Invoke* functions are implemented by using reflection. Reflection have very huge overhead when calling and should be avoided. Coroutine, on the other hand, has very little or no overhead (depending on which StartCoroutine version you using), so, it is a better alternative for Invoke*."
That comment refers to the $$anonymous$$ethodBase.Invoke method from System.Reflection, not InvokeRepeating.
The string form of both InvokeRepeating and StartCoroutine must use reflection at least once to deter$$anonymous$$e the method to call. I'd bet that its only done once for invoke repeating, rather then every time the method is called. If you are really worried about performance do a benchmark.
Answer by jashan · Aug 27, 2018 at 07:51 AM
In addition to what others have said (Invoke using reflection which causes a significant impact on performance, and being extremely error prone by using strings to call methods), there is another very big issue: Invoke and InvokeRepeating are based on Time.timeScale.
So if you use them, for example, in a settings menu that is shown during pause, with pause being implemented by setting Time.timeScale to 0, methods called by invoke will simply never be called because the time never "passes".
So, I would strongly recommend to never use Invoke or InvokeRepeating and always use Coroutines or another approach instead.
Answer by BMayne · Jan 11, 2015 at 05:28 AM
Hey There,
As emongev was saying Invoke uses reflection to call your functions. It's not the fastest thing in the world but then again Unity runs on reflection. StartCoroutine uses and ienumerable and an ienumerator to iterate over a list of steps that you define.
One huge difference is that a Coroutine is a time share, meaning it acts like a thread even though it's not. It allows you to wait for a process to finish without stopping execution of your project. When that process is done it picks up where it left off.
(Super basic explanation of what it really is doing)
.
My Advice **
Never use Invoke or Invoke Repeating. It can make your code very difficult to debug. You can very easily implement a system using update.
Your answer
Follow this Question
Related Questions
Shooting Projectiles With controlling attackSpeed 0 Answers
Invoke repeating and StartCoroutine 1 Answer
Custom fixed update cycle? 6 Answers
Invoking does not work, but why? 1 Answer
InvokeRepeating with parameters 2 Answers