I have an issue where my game suddenly stops for a second and then continues. And I think it has something to do with my performance so I took at look at the profiler:

I tried to take a screenshot as soon as the crack happened:

enter image description here

enter image description here

However, since I am a bit new to optimization could anyone give me a helping hand on what might be the problem here?

  • \$\begingroup\$ From a first glance you can see that the crack happens excactly as the GC ( Garbage Collector ) does it's magic. Optimization in general is a thing that is hardly doable here since it requires to look at the complete code and investigate allocation of memory/object-references and if they are stuck or not freed soon enough etc. But as a hint I would say look if you can free some resources earlier or if some are kept initiated even without them needing to be initiated. \$\endgroup\$ – Nico Oct 27 '17 at 9:47

As Nico says, your profiler seems to show a big spike of garbage collector activity, which is consistent with the symptom of a sudden isolated stall.

This happens when your scripts allocate and then discard heap memory frequently. When a heap allocation request comes in and there's no longer enough untouched space left on the game's heap to fulfill it, the .Net/Mono runtime puts everything on hold while the garbage collector checks which previous allocations are no longer being used and clears them out, compacting the used portion heap to leave a nice big open space again. In a large & complicated game, a full sweep can take a significant amount of time.

To avoid this, take a look into which scripts are allocating lots of heap memory managed by the garbage collector — that's the GC Alloc column in the profiler, where I notice one line there allocated 2.0 MB in this frame. If that's happening frequently then it will definitely add up.

2.0 MB could be two 512 x 512 uncompressed RGBA textures, for instance. If you're allocating big blocks of memory like this, see if there are ways you can re-use them like a circular buffer or object pool, rather than continually allocating new ones. If you need temporary RenderTextures in particular, Unity has a built-in pool you can tap into with RenderTexture.Get/ReleaseTemporary.

Also watch for cases where two different scripts make a modified copy of a source asset each, even if the modification they needed was the same — you can cache and re-serve the existing copy instead of re-doing the work on a new one.

Creating new instances of reference types like Arrays/Lists, instantiating GameObjects, attaching Components, or modifying strings without a pre-allocated StringBuilder all create heap allocations too, though typically on a much smaller scale than textures, and more easily reclaimed.

If you're using Unity methods that return new arrays, like RaycastAll, check to see if they have a NonAlloc variant that lets you pass in your own buffer to populate, letting you re-use the same memory between calls.

For more information about reducing problems from garbage collection, see this Unity tutorial which goes into a lot of detail. :)


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.