- Home /
WaitForSeconds(3) on Android waits less than expected
I am seeing some very strange behaviour with WaitForSeconds function in a coroutine while running on Android.
If I run the following TestCoroutine on Unity Editor everything works fine but when running on Android I see that the WaitForSeconds(3) waits for only approximately 1 second.
private IEnumerator TestCoroutine() {
Debug.Log("!@! 0 TestCoroutine Time.timeScale: " + Time.timeScale);
yield return new WaitForSeconds(3);
Debug.Log("!@! 1 TestCoroutine Time.timeScale: " + Time.timeScale);
yield return new WaitForSecondsRealtime(3);
Debug.Log("!@! 2 TestCoroutine Time.timeScale: " + Time.timeScale);
}
This returns (in logcat):
2019-08-26 16:19:52.676 14700-14793/? I/Unity: !@! 0 TestCoroutine Time.timeScale: 1
2019-08-26 16:19:54.408 14700-14793/? I/Unity: !@! 1 TestCoroutine Time.timeScale: 1
2019-08-26 16:19:57.426 14700-14793/? I/Unity: !@! 2 TestCoroutine Time.timeScale: 1
As you can see the timestamp difference between the first call and the second is 1.732 even though we call WaitForSeconds(3). After doing WaitForSecondsRealtime(3) we can see the timestamp difference is 3.018 (0.018 is probably the time until the next frame was called).
Clarifications:
This only happens in Android.
The coroutine is being called with a simple StartCoroutine(TestCoroutine());
This happens around some ApplicationFocus stuff. Specifically: minimising the app and returning to the app.
There is a call to StopAllCoroutines in the code where this TestCoroutine is also being called but it makes no difference whether it is commented out or not.
Any help will be appreciated whether you've seen something similar or just have an idea!
Thanks!
There are some factors which can mean the actual amount of time waited does not precisely match the amount of time specified:
Start waiting at the end of the current frame. If you start WaitForSeconds with duration 't' in a long frame (for example, one which has a long operation which blocks the main thread such as some synchronous loading), the coroutine will return 't' seconds after the end of the frame, not 't' seconds after it was called.
Allow the coroutine to resume on the first frame after 't' seconds has passed, not exactly after 't' seconds has passed.
https://docs.unity3d.com/ScriptReference/WaitForSeconds.html
I would agree with you if I was seeing a longer than 3 seconds pause when calling WaitForSeconds... But this pauses the execution of the coroutine for less than 3 seconds!
can you try doing something like this?
float timer = 0;
while(timer < 3)
{
timer += Time.deltaTime;
Debug.Log("!@! 4 TestCoroutine Time.timeScale: " + Time.timeScale + "and timer is " + timer);
}
Debug.Log("!@! 4 TestCoroutine Time.timeScale: " + Time.timeScale + "and timer is: " + timer);
if you fire 2 coroutines one with they waitforseconds and ther other with this while both should be fired and end at the same time since both depend on the time.deltatime, can you make sure that behaviour continue happening?
Answer by amoswazana · Aug 28, 2019 at 08:00 AM
Using WaitForSecondsRealtime(3) instead of WaitForSeconds(3) solved the issue for me.
Apparently the reason for this bug was an issue with deltaTime being updated while the app was in the background. I ran a test coroutine printing the Time.deltaTime from the same place as the coroutine that had the bug then I saw the value increase as expected twice and suddenly increase by the time I was focused out of the app.
For example:
private IEnumerator TestCoroutine2() {
float timer = 0;
while (timer < 3) {
timer += Time.deltaTime;
Debug.Log("!@! 4 TestCoroutine timer is " + timer);
yield return null;
}
Debug.Log("!@! 5 TestCoroutine timer is: " + timer);
}
Would return:
2019-08-27 12:59:36.233 4688-4794/? I/Unity: !@! 4 TestCoroutine timer is 0.02
2019-08-27 12:59:36.262 4688-4794/? I/Unity: !@! 4 TestCoroutine timer is 0.1206014
2019-08-27 12:59:36.417 4688-4794/? I/Unity: !@! 4 TestCoroutine timer is 10.1206
2019-08-27 12:59:37.167 4688-4794/? I/Unity: !@! 5 TestCoroutine timer is: 10.1206
This happened to me only on Android.
Answer by PKU_DZY · Aug 27, 2019 at 12:32 PM
You can refer this article: https://docs.unity3d.com/Manual/ExecutionOrder.html
WaitForSeconds is a yield instruction which is executed after update and before LateUpdate in main thread to check if given condition is fulfilled, so the error exists but less than a frame duration.
please read the comments, the error is about 10 seconds long, is not a frame issue
Your answer
Follow this Question
Related Questions
Script works in the editor but not in builds 3 Answers
Rotate an object using Quaternion.RotateTowards() inside a Coroutine? 1 Answer
I'm having trouble with Coroutines.. 2 Answers
How to solve while loop lags 1 Answer
Doing WaitForSeconds in C# 0 Answers