So my students and I have build an arcade machine, to showcase our productions to the rest of the school. Works great. It has a “hub” from where all games are launched. Also great. But this hub has some UI elements which are animated from the Animator system. Colors, and transforms and such. Those run forever. When the hub has been running for a couple of days, those animations begin to fail. First they’ll get slower. And slower. Until finally they are so slow, that they seem to not animate anymore. That happens around day four.
Everything else is still very responsive. Inputs to the hub, and general “Update” functions seem to run normally. So it is not the project itself that slows down, only the animation system internally.
My own little theory is that each cycle will increment some internal state. And then memory, over time, will get filled with garbage, which the garbage collector fails to clean, due to it not being de-referenced. Something.
My fix for now is to destroy, and recreate certain UI elements (Having made them into prefabs that I can load from “Resources”), when they have been running for some time. But it still feels like a hack, that should be unnecessary.
Anybody having a clue what’s going on, and how to fix it for real? Is it a bug, or is it simply would is to be expected when having a game/project just run for days on end?
Untiy’s animations uses an internal timer to keep track of how long it’s been playing. That timer just increments forever.
This means (approximately) that every frame, Time.deltaTime is added to the time value. Due to how floating point numbers work, that starts breaking as the total time is larger, as the number can’t handle that much precision.
Now, this should be fine for a couple of days if Unity was using a double to store the time, but they might be using a float. I’m not sure.
One way you could try to fix this in a less destructive way is to grab the Animator’s playableGraph, and set it’s time back to 0 at regular intervals. If the problem is an clock internal to the Animator (which is what it sounds like, since other things are responsive), that should fix things. You might want to also reset the time on all of the playables in that graph.
I would too, but when I tried to emulate the problem manually using doubles, adding 1/60 to 606024*10 (10 days) gave an imprecision of -5,43271504171994E-11, ie. almost nothing. So this shouldn’t be noticeable after just 3 days with such a setup.
Floats, on the other hand, is completely unable to add 1/60 seconds to 2 days (the result is just 2 days), so honestly my test might be off?
If you can use seconds in a game (which you can), can you not just create a virtual clock and reset back to 0 (like how a digital clock works), when it reaches obvious 60ths/12ths, or does this come under the eventual bloated floating point precision as Baste says?
I actually didn’t fix it in the hub itself. I don’t know how I would, as it seems be because of the internal clock that is based on floats. And floats are too unprecise for animation timings and such the higher they are.
But what I did do was let the arcade hub create a new Windows process of a new instance of itself, and then close down. It does so every night at 5:30 am, unless it registers usage. When it hasn’t been in use for 5 minutes, and 5:30 is reached (Or surpassed), it shuts down, and restarts. Works great. But… it is a hack
I know this is an old thread, but I’m running into an issue much like this in Unity version 2021.3.5f1 and there doesn’t seem to be much information online regarding long-running applications in Unity. I have tried the fix of iterating over all playable graphs on an animator after some period of time to reset them, but that doesn’t seem to help. Forcibly restarting the application isn’t a valid option for me. Has anyone else managed to uncover any information or workarounds for this?
I put together a test scene and submitted this issue to Unity. Please take a moment to vote on it:
If you run into this issue, a workaround is resetting the normalized time on the animator component to zero periodically by calling the relevant Animator.Play() method and passing in normalized time.