- Home /
How to get function to run every x seconds and then every y seconds?
I have a coroutine that I want to run every 10 seconds, and then every 15 seconds. So that would look like coroutine runs for the first time,
10 seconds later it runs for the second time,
15 seconds later it runs for the third time,
10 seconds later it runs for the fourth time,
...
I've tried two parallel InvokeRepeatings at an offset with different delays, but one will always be called at least twice before the other one. I've tried:
private IEnumerator Timing()
{
yield return new WaitForSeconds(delays[state % 2]);
state++;
ChangeState();
}
but I don't know how to get this running continuously without messing up the coroutine that this one calls. I'm also trying to get this as efficient as possible because there will be many objects with this script. Any help would be appreciated, even if you can just point me in the right direction.
Answer by Shen-Kit · Apr 24, 2020 at 03:04 AM
What I would do in that situation is have a bool (e.g. "oddRun"/"evenRun") and have an if else statement. If it oddRun = true, yield return new WaitForSeconds(10);
, if oddRun = false, yield return new WaitForSeconds(15);
You will want to put the logic of your coroutine before this (see my example below). Also you need to use StartCoroutine(CoroutineName())
you can't just call a coroutine by its name.
bool oddRun = true;
private IEnumerator Coroutine_you_want_to_run()
{
(Put the logic you want to run in the coroutine here)
(Can put a Debug.Log("Test") to test whether the timing is working)
if (oddRun) {
oddRun = false;
yield return new WaitForSeconds(10);
}
else {
oddRun = true;
yield return new WaitForSeconds(15);
}
StartCoroutine(Coroutine_you_want_to_run());
}
If this worked, please mark it as answered. If you still have questions, feel free to ask I'm happy to help :)
Thanks for your answer.
Your solution is a recursive coroutine, right? I'm curious as to whether that introduces any overhead especially after running hundreds of times throughout the scene's lifetime. Or would it not really be a problem since the last line of the coroutine is reached?
While I'm not an expert or anything on this topic, I am fairly certain that this would not introduce any problems as the coroutine finishes the moment it calls itself again.
Here's what I ended up going with:
private IEnumerator Ti$$anonymous$$g()
{
ChangeState();
yield return new WaitForSeconds(delays[state % 2]);
state++;
StartCoroutine(Ti$$anonymous$$g());
}
It just seems more elegant.
Answer by yummy81 · Apr 24, 2020 at 03:41 PM
something like that?
IEnumerator YourCoroutine(){
while(true){
// code here
yield return new WaitForSeconds(10f);
// code here
yield return new WaitForSeconds(15f);
}
}
That seems like it will work but I'm not really sure if there will be a severe performance impact if hundreds of gameobjects are running a while loop simultaneously for hours.
It can be optimised a little, but...
IEnumerator YourCoroutine(){
var wait1 = new WaitForSeconds(10f);
var wait2 = new WaitForSeconds(15f);
while(true){
// code here
yield return wait1;
// code here
yield return wait2;
}
}
It's hard to imagine, how the coroutine would look like without some sort of infinite loop: while(true) or for(;;;), if it were to run for hours...
Thank you for your replies, but it seems like for my applications recursive is much faster than a while loop.
Your answer
Follow this Question
Related Questions
Invoke.Repeating doesn't really "care" about repeat time? 1 Answer
Is it possible to change Invoke Repeating rate on the fly? 3 Answers
convert timer from update() to coroutine or invokerepeating 0 Answers
Best practise time-based, repeating function calls: InvokeRepeating vs CustomSolution 0 Answers
how to restart coroutine on event? 2 Answers