See the sample project here: https://github.com/omundy/dig250-unity-performance
"Profiling should not be an afterthought or something left until the final stages of development. Instead, integrate profiling into your development process from the very beginning." —Eugene Martynenko1
- The most important metric of a performant game is a high Frames Per Second (FPS) rate, accessed in the Stats window (Game View).
- To increase your game's performance, simply lessen the work of the CPU, GPU, memory, and network.
- A frame rate of 60 FPS is optimal. Anything less than 30 FPS will cause noticeable stutter.
Many performance gains can come from reducing and reusing CPU or memory.
- Always Cache References - When you need a reference to a component, property, camera, or script, do so in
Awake()orStart()and store the reference in a variable accessible by the entire class. This improves performance because your script won't have to look up the same reference over and over inUpdate(). 2
Rigidbody rb; // do this for components...
Vector3 distanceToEnemy; // variables...
Camera cam; // the main camera...
Transform myTransform; // and the transform
private void Awake() {
rb = GetComponent<Rigidbody>();
cam = Camera.main;
myTransform = transform;
}
void Update() {
distanceToEnemy = myTransform.position - enemyPosition;
}- When you remove (
Destroy) objects from your game their data is no longer needed. - The memory set aside to store that data, "Garbage", must be freed before it can be reused.
- Garbage Collection is the process that makes previously used memory available again.
- It can cause big performance problems (a frame rate stutter) if not properly handled.
- A pattern to decrease garbage collection (and stutter) created by adding and removing objects from memory.
- Start by pre-instantiating objects you need at any specific moment before the scene starts.
- Place the objects off-camera in a "pool" so they are in memory, but the CPU/GPU doesn't have to draw them.
- When you need an object, pull it from the pool. Once finished with it, don't destroy it (which causes garbage collection), rather put it back in the pool to reuse later.
- See more about Object Pooling in Unity
In Unity, retrieving strings from game Objects will create a duplicate of the string, which will need to be garbage collected. Some ways to save memory:
- Don't use
gameObject.tag == "string"; UsingCompareTag(string)instead does not add to the heap resulting in a ~27% increase in performance. See: Unity 5 Game Optimization by Chris Dickinson and Unity forum - Don't concat strings in loops or
Update(). See: Unity Manual: Understanding Automatic Memory Management
- Daniel Ilett Unity Tips: Garbage Collection, 2019
- Unity Manual: Garbage collection best practices
- Unity Tutorial: Fixing Performance Problems
- Regularly check the Profiler Window to identify obvious dips in performance.
- Since changes in one "performance area" can affect others, test everything as you make each improvement.
- A draw call is the command the CPU sends to your GPU to draw geometry on your screen
- Effectively, the number of objects being drawn.
- Keep this number down (<2000 desktop and <200 mobile) to maintain good performance.
- Use spritesheets (a.k.a. texture atlas) to group similar bitmap images and reduce the draw calls to your GPU
- Use pixel resolutions that are Power of 2 (128,256,512,1024, etc.) which can be compressed better.
- Unity Manual: Optimizing graphics performance
- Unity CPU Optimization: Is Your Game… Draw Call Bound? (2020)
- Best Practices to Improve Performance on Mobile Builds in Unity
- Object Pooling
- Dynamic Framerate
- Reuse lists (instead of arrays)
- Unity Manual: Mobile Optimization
If you have a lot of UI in your game start with this video Unite Europe 2017: Squeezing Unity: Tips for raising performance
- From the video, the first thing to know is that during runtime, if you change even one component that needs to be redrawn it sets a "dirty" flag on the entire Canvas (the first parent technically) of that changed object.
- When a Canvas is marked dirty then ALL the geometries in that Canvas need to be recomputed on that frame causing a major performance hit. Several of the tips below help to address this issue.
- Organize your UI elements into multiple or nested canvases based on when they are updated. These "islands" will help to isolate elements into groups that should be redrawn together so you won't have to redraw all elements across your UI.
- Use prefabs to nest elements #20
- Disable the Raycast Target property for all non-interactive elements to avoid the amount of work the raycaster must do on each frame
- Turn off Images components you don't need to avoid draw calls #15
- Do not use alpha to show / hide elements
- Be careful using
Canvas.ForceUpdateCanvases()because there is a serious performance hit. - How to hide a Canvas Disable the Canvas Component itself
- Unity Tutorial: Optimizing Unity UI
- Unity Create: Some of the best optimization tips for Unity UI
- Unity UI Best Practices
- Marking an object as static (the check box at top right of the Inspector) "can save on runtime calculations, and potentially improve performance." (Unity), depending on things like the overall number and complexity of the objects involved, whether or not you use lighting in your game.
- Keep in mind that this will increase the filesize of your build (and thus memory during play) "Using static batching requires additional memory for storing the combined geometry."
Depending on your game's requirements, baking your lights can increase performance a lot, especially on mobile. A lightmap is essentialy a texture that includes surface information like color (albedo) and relief (normals), as it is seen with direct and indirect static lights in the scene. The data baked into lightmaps cannot change at runtime. Real-time lights can be overlaid and used additively on top of a lightmapped scene, but cannot interactively change the lightmaps themselves.
- Know how the camera frustrum and clipping planes work https://docs.unity3d.com/Manual/UnderstandingFrustum.html
- Did you bake your fonts (change from dynamic to static)
- Consider the Order of Execution for Event Functions and make sure you aren't causing extra work.
General best practices include:
- Restart Unity once a while
- Delete the contents of the project Library (resets package caches and others that Unity rebuilds). Quit Unity, delete contents, then start again.
- Use Assembly definitions
https://discussions.unity.com/t/introducing-the-editor-iteration-profiler/794996
- Unity Scripting Reference
- Chapter 8 in Halpern, Jared. Developing 2D Games with Unity. APress, 2019.
- Tomas Macek The 10 Most Common Mistakes That Unity Developers Make
Footnotes
-
Martynenko, Eugene. “10 Tips for Optimizing Performance in Unity Games.” (2024) ↩
-
Fahir Mehovic. “Optimize Your Games In Unity – The Ultimate Guide.” (2021) ↩


