AnimationStates allocate piles of memory

I just discovered something that I wish I’d known a long time ago…

Referring to AnimationStates in an update loop, such as in the following code…

function Update () {
     if (animation["idle"].weight == 1) {
         // do stuff
     }
}

… allocates massive amounts of memory each update. My first iPhone game ended up using this kind of logic quite a bit to determine animation behavior, when to play what clip, with what weight, etc. etc. Turns out it was causing the garbage collector to run overtime due to the fact that each time you use an animation state in this manner, you’re burning memory. On the contrary…

var idle : AnimationState;
function Awake () {
     idle = animation["idle"];
}

function Update () {
     if (idle.weight == 1) {
          // do stuff
     }
}

…causes no runtime allocation. Just thought others might like to know.

These little optimization hints are much appreciated!

is the general rule to avoid strings in Updates as much as possible? i’m starting optimization in my game now and i think i have quite a few GameObject.Find(“blah”) throughout which i’m thinking probably isn’t such a good idea.

As a general rule, whenever you’re referring to other objects or components via script on a frame-to-frame basis, its best to cache a reference to that object/component in a variable. It is both faster, and does not require repeated memory allocation. If you need to find another object by name with GameObject.Find(), try to do it only once (such as in an Awake () function) and store it in a variable for repeated use.

If you’re ever in doubt as to whether you’re scripts are causing memory allocations every frame, build your app in xcode and choose Run > Start with Performance Tool > Activity Monitor from the pull down menus. If your app’s memory usage is slowly climbing for no apparent reason, you know you have allocations occurring every frame. After about 4 mb accumulate, the garbage collector will run and you will experience a small performance hit… which is really annoying if you’re making an action game! (FYI, a lot of people observe this behavior and think its memory leaks, but this is not the case - just garbage accumulating and being discarded.)

My first iphone game ended up allocating a fair amount of tiny junk all the time and as such wil experience these performance hits for a couple seconds once every 2-3 minutes during play. I hope to write cleaner code and avoid it altogether in my current project - ideally garbage collection will almost never need to run in the midst of gameplay.

Sounds like a good tip. I tried running the Activity Monitor but I keep getting a “Target terminated too early to collect data”. App runs just fine though.

Another way to find it out: set ENABLE_INTERNAL_PROFILER to 1 (instead of 0) in AppController.mm. Run you game on iPhone and check XCode console output. If you see “used heap” in “mono-memory” section increasing with each frame - you have temporary allocations in your scripts.

I tried doing this but as the Instruments app opens it suddenly will say “Target terminated too early to collect data” and doesn’t read anything.

Any ideas what’s going on here?

Thanks for the great tip, PirateNinja! I had noticed this behaviour myself (gradually climbing memory usage) but hadn’t quite copped that a lot of it was likely allocations from just accessing various properties in Update.

Code:

var idle : AnimationState;
function Awake () {
idle = animation[“idle”];
}

function Update () {
if (idle.weight == 1) {
// do stuff
}
}

Just wondering. Would this cache the same way (and be as beneficial) if I were to assign the “idle” animation to the “idle” variable in the Unity interface instead of an Awake function? Thanks.

That code you have there is exactly what you should do. Assigning through the inspector would achieve the same result, but I’ve personally gotten in the habit of assigning it all via script because I’m doing a lot of animation setup in my awake function anyway (setting layers, wrap modes, speeds and such).

Thanks for the fast reply:) Assigning through script definitely sounds like the way to go. I’ll know for next time. Thanks again.

Sorry to bring this up again, but what happens in the case of:

animation.CrossFade(“Run”);

Is this still getting treated as a string and allocating memory all the time?

Thanks!

“Run” is a string and as such is allocated just to be dropped again.
If you don’t want that to happen, cache it in a string array and use an array entry instead

Thanks, man. Makes total sense!

I just make a string array and hopefully all that nasty memory allocation nonsense should ease off! :slight_smile:

Animation.Play(“blah”) or Animation.CrossFade(“blah”) do not allocate memory in my tests. I use statements like these constantly (multiple times per frame) and my mono heap does not grow each frame.

Thats clear pirate. it will only rise the heap once and after that use the pooled memory. but its still an object creation and destruction again and again.

So then… pulling the names of animation clips from a pre-defined array won’t save any memory, but it might require less cpu?

Creating/destroying a string over and over again in this manner must have a very tiny effect, I do it dozens of times per second and have experienced no adverse effects.

So I’m seeing A LOT less movement in the heap since I removed all my strings of doom, though something is still going on for the heap to keep growing albeit slower.

Thanks for the heads up(s) … very good to know!

After browsing through this thread, i’m very happy that in my current Game, i recently changed all of the code to cache all AnimationState’s to variables in Awake() .
As it seems, this saves me from having nightmarish support-experiences after the game is out in the wild…

I find this interesting… I’m assuming its string related as to why that was blowing out…

But what interests me is that I’ve never checked for whether an animation is playing, I generally make co-routines that wait a specified amount of time (the length of an animation) so I always know what has been played and what hasn’t, etc.

I know that sounds like far more work than required, but it means I’m not putting an if statement into an Update loop (I’m a code Nazi, i hate anything happening anywhere that doesn’t need to).

One of these days, I really should download one of the Unity example projects and see how ‘normal people’ do these things… I kinda just fumble my way through until something works :stuck_out_tongue: