- Home /
Coroutines (likely) running far too slow on Android, what's the issue?
Windows build is lightning fast but the android version is unacceptably slow. Something that was near instantaneous takes around 5 seconds on Android. Searching the interwebs on this topic, using FixedUpdate was brought up, but since I've more than 30 coroutines all over and coroutines should work fine on Android, and this would be taxing to convert all coroutines over, I thought I'd appeal to you all first. I've coroutines all over for various tasks, but here's an example fade piece:
public void BeginFade()
{
StartCoroutine(FadeIt_Image());
}
IEnumerator FadeIt_Image()
{
yield return new WaitForSeconds(delay);
for (int i = 0; i < fadetovalue; i++)
{
subject.GetComponent<Image>().color = new Color32(System.Convert.ToByte(subject.GetComponent<Image>().color.r * 255), System.Convert.ToByte(subject.GetComponent<Image>().color.g * 255), System.Convert.ToByte(subject.GetComponent<Image>().color.b * 255), System.Convert.ToByte(i));
//yield return new WaitForSeconds(.001f);
yield return null;
i = i + speed;
}
}
This is just a slimmed down simple one, but there's coroutines that move and fade and change menu values and they all uniformly take something like 5 seconds to perform. Here's some of the additional details that may get brought up:
No coroutines are kicked off with Update functions, but the opening flourish does kick one off with a Start function. The rest are action based like with button activation. The idea to try FixedUpdate (which if we can't solve this I'll be forced to try) came from here: https://stackoverflow.com/questions/69067286/my-coroutine-is-running-slower-on-unity-android-aplication
I tried various yield times and all are the same 5 second slug (you can see what is active in the code above is yield return null, but waitforseconds is commented out which failed and I tried waitforrealtime which also failed as was referenced here:https://www.reddit.com/r/Unity2D/comments/p9pu0d/my_coroutines_run_slower_on_my_phone_than_on_my/
Test phone is OnePlus 6T and runs other Unity apps fine. Buddy is running a Galaxy s22 who also reported a slow move time so "the phone is slow" isn't the problem.
I took out all images and objects and ran with just Unity code and it still does this so no bloat objects are being used that would slow this down.
Only one Coroutine is running at a time throughout most of the time. I verified through debugs that none of them are stuck, they just take the previously mentioned 5~ seconds to complete
Thank you for any suggestions you all may have.
General update as I do the rounds on parts of this code: No fix or responses yet, but small bit of added info: There are 34 coroutine instances and I have failed to swap any of them with FixedUpdate, nor do I want to entertain that at this point honestly. I did change out all yields with "WaitForSecondsRealTime" at .01f, amusingly the android lag is precisely the same amount of time, right at around 5 seconds for approximately 1 second actions on Windows. I have an FPS on there now, it shows a fairly constant 30 FPS on Android, not sure how to vary that at all. Windows build bounces around from 70ish to 130ish. Looking for exclusively a solution that doesn't gut the coroutines at this point, so along those lines, suggestions are welcome, thank you.
Answer by DoodleDangWang · May 26 at 05:44 PM
I have concluded that coroutines universally are just not appropriate for accurate timed actions on Android. As was recommended before, Fixed Update will have to be used. Stack Overflow example below for performing similar tasks, and therefore will start the process of gutting all coroutines from my code. https://stackoverflow.com/questions/54302191/right-way-to-manage-time-event-in-unity
Answer by rh_galaxy · May 07 at 04:41 AM
I can't say anything about the speed of the code, but a Coroutine will depend on framerate. It will run until the next yield every frame. So in your example if speed is 1 you will increase fadetovalue by 1 every frame, meaning that if the framerate is 10 instead of 60 it will take 6 times as long. The normal thing to do is to base it on time instead - increase fadetovalue by Time.deltaTime*speedoffade. I don't like coroutines and do my things directly in Update, and this is one of the reasons.
Thanks, I'll give that a try. Indeed, I believe all my coroutines have some static value in a for loop so there may be something to that. One other thing I haven't posted yet as I haven't thoroughly tested it yet is I noticed that the active project variant in Windows was also starting to get sluggish, almost as slow as the Android one. Not sure if that's related to your suggestion above, but I'll try it anyway and report back...
Sorry for the late return: so nah, adding Time.deltaTime* to the for integer doesn't do anything noticeable. In the case of fades, I'm using fadetovalue to stop the integer at the fade value (so if an image is fading in from 0 but I didn't want it to be full at 255, fadetovalue can set it lower so it maintains translucency). Something I hadn't posted was the move code which does not use For loops, but While loops instead, and yes, moves are just as slow as fades on android. Sample Move code for perusal:
while (fasterTime <= 1)
{
yield return new WaitForSecondsRealtime(.001f);
//yield return null;
fasterTime += Time.deltaTime;// / MoveTime;
SecondSubject.transform.localPosition = Vector3.Lerp(SecondSubject.transform.localPosition, Point2_To.localPosition, Mathf.SmoothStep(0, 1, Mathf.SmoothStep(0, 1, fasterTime)));
SecondSubject.transform.rotation = Quaternion.Slerp(SecondSubject.transform.rotation, Point2_To.rotation, Mathf.SmoothStep(0, 1, Mathf.SmoothStep(0, 1, fasterTime)));
}
I went ahead and nixxed the MoveTime variable in case that too threw you all off and no, has no effect on Android, still slow. Incidentally, I was already using Time.deltaTime in this loop as you suggested. As you mentioned, using FixedUpdate is preferable and yes, I can try that, but I need to know then: are coroutines 100% across the board bonkers slow on Android for 100% of devs? If no, then I don't buy that my solution is only to fall to FixedUpdate. I've done something to cause Android-exclusive unacceptable sluggishness tethered emanating around coroutines and needs to be fixed, not replaced. I'll continue to poke at this and I'll post updates as I find anything that changes the Android speed, I do appreciate any thoughts on anything to try here as I'm about full on stuck.