Overview

3 Memory allocations and performance

This chapter explains why memory behavior is a major part of performance in Unity games. It shows that poor allocation habits can cause sudden slowdowns, cache misses, and even crashes, especially when the heap becomes fragmented or the garbage collector interrupts gameplay. The central idea is that memory management should be planned around gameplay flow so the game stays smooth and predictable.

A key theme is fragmentation: when objects are allocated and freed in an unstructured way, the heap can end up full of holes that are too small for new allocations, even if the total free memory seems sufficient. The chapter also emphasizes that Unity’s garbage collector creates its own problems because it does not free memory immediately, can run at unpredictable times, consumes CPU, and can worsen fragmentation. For this reason, temporary data should stay off the heap whenever possible, and allocations should be grouped and released in a stack-like order.

To reduce these issues, the chapter recommends object pools and level-based allocation patterns. Rather than constantly instantiating and destroying objects, developers should preallocate the objects and data a level needs, reuse them during play, and release them together when the level ends. It also warns about common pooling mistakes, such as failing to reinitialize reused objects or mixing visual state with gameplay logic, and stresses that pool sizes should be chosen based on real design limits and device constraints so they never need to resize during gameplay.

An example of fragmented heap memory, with holes of unused memory surrounded by allocated memory.
This figure shows how our three arrays look in memory, with array1 allocated first, followed by array2 and array3.
After deleting array1 and array3, we now have two holes in memory on either side of array2.
We have 2048 bytes of memory free, but if we try to allocate an array of 1536 bytes, we’ll run out of memory because the biggest contiguous space is 1024 bytes.
In Unity, freed memory cannot be reused until the garbage collector runs. If we allocate and deallocate objects often, we’ll use more memory than expected.
The variable array is allocated on the stack, while the contents, 1,000 bytes, are allocated on the heap.
Screenshot from the Unity profiler
Frequent allocation and deallocation of memory can lead to memory fragmentation, eventually crashing the program
We allocated all the memory we needed when loading the level, and we used only that memory until we unloaded the level, regardless of how many enemies were spawned and removed.
Hide all enemies task
New feature to stop enemies from immediately moving when spawned.
Bug report newly assigned to us about some enemies moving immediately.
An ideal memory allocation, with common data allocated first, then level-specific data.
A graph showing what our memory usage looks like when loading the main menu, and then entering and exiting the first level.
A graph showing what our memory usage looks like when loading and unloading multiple levels. We load common data first, such as menus and objects used across all levels. Then, for each level, we load level-specific data, such as enemies or terrain objects.

Summary

  • Memory fragmentation is when our memory is full of holes. This is bad because the memory manager allocates data in contiguous chunks. If the memory manager can’t find a chunk big enough for our data, our game will crash.
  • A useful way to reduce memory fragmentation is to organize heap data by lifetime: allocate related data together, keep it alive for the same duration, and release it together or in reverse order when possible.
  • It is a good idea to avoid triggering the garbage collector during gameplay because it is hard to predict when it will run and can impact performance.
  • The garbage collector can also cause memory fragmentation because memory can’t be reused until it runs.
  • Object pools allow us to recycle data by allocating everything we need once and reusing it as needed.
  • Object pools help limit memory fragmentation and reduce garbage-collector triggers.
  • In an ideal situation, we want to allocate all the common data we need when the game loads and keep it in memory until unloading the game.
  • We want to allocate all the level-specific data only when loading a level and keep it in memory until the level is complete.
  • We want to avoid allocating and deallocating memory during gameplay.

FAQ

What is memory fragmentation in Unity, and why does it matter? Memory fragmentation happens when heap memory has gaps or “holes” left behind by deallocated objects. Even if the total free memory is large enough, Unity may still fail to allocate a new object if no single contiguous block is big enough. This can lead to crashes and reduced performance.
Why can deallocating objects in a different order than they were allocated cause fragmentation? When objects are freed out of order, the heap can be left with unused spaces between still-allocated objects. These gaps create fragmented memory. The more often this happens, the harder it becomes to find large contiguous blocks for new allocations.
Why is memory fragmentation a problem in the heap but not in the stack? The stack automatically deallocates data in reverse order of allocation, which keeps memory neatly organized and contiguous. The heap does not enforce that order, so it can become fragmented over time.
How does the garbage collector affect game performance in Unity? The garbage collector uses CPU time to find and remove unused objects. Since Unity can run GC automatically during gameplay, it may cause sudden frame drops or stuttering at unpredictable times, hurting the player experience.
Why doesn’t Unity immediately reuse memory after calling Destroy()? Calling Destroy() only marks the object for later removal. The memory is not reclaimed until the garbage collector runs, so the space cannot be reused immediately by new objects.
What are the main drawbacks of relying on the garbage collector in games? The three main drawbacks are: memory is not freed immediately, GC can cause performance spikes when it runs, and Unity’s GC does not compact memory, which can contribute to fragmentation.
What is an object pool, and how does it help performance? An object pool preallocates a set of objects ahead of time and reuses them instead of constantly creating and destroying new ones. This reduces heap allocations, lowers GC pressure, and helps prevent memory fragmentation.
What should you do when an object pool runs out of room? In the chapter’s guidance, you should not resize the pool during gameplay. Instead, log the issue and adjust the pool size or game design later if needed. The pool should be sized to match the level’s maximum expected usage and the target device’s memory limits.
What is the most common bug when using object pools? The most common bug is forgetting to reinitialize pooled objects when they are reused. If gameplay data is not reset, a reused object may inherit stale state from its previous use and behave incorrectly.
Why should visual data and logic data be kept separate in a DOD-style object pool? Keeping them separate makes the code easier to save, test, and run on servers. Logic data can be stored independently of GameObjects, which helps avoid bugs and makes it possible to simulate gameplay without rendering visuals.

pro $24.99 per month

  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose one free eBook per month to keep
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime

lite $19.99 per month

  • access to all Manning books, including MEAPs!

team

5, 10 or 20 seats+ for your team - learn more


choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • High Performance Unity Game Development ebook for free
choose your plan

team

monthly
annual
$49.99
$499.99
only $41.67 per month
  • five seats for your team
  • access to all Manning books, MEAPs, liveVideos, liveProjects, and audiobooks!
  • choose another free product every time you renew
  • choose twelve free products per year
  • exclusive 50% discount on all purchases
  • renews monthly, pause or cancel renewal anytime
  • renews annually, pause or cancel renewal anytime
  • High Performance Unity Game Development ebook for free