Crave For Games

The text below is one of the notes from the StoneDrop development log. If you want a list of only technical articles you can go to the Articles page.
Unity content optimizations

Key points from a Unite talk about content optimization techniques for Unity.

Video 1. Let's Talk (Content) Optimization. November 2016, Unite


- instantiation is a serialization, memory buffer copy, deserialization

- everything is serialized without any data checks or compression

- scenes, Resources and AssetBundles are build atop of SerializedFiles - binary data with header (indexes of assets, their byte offsets in the file, type tree and type tree hashes)

- prefab loading is faster in editor, but cloning is faster in non-editor builds (to load one large object is slower than to assemble it from small cloneable parts)

- to clone a prefab is much faster than manually assemble it - no additional lookups or typechecks are performed

- it's more performant for UI prefabs with a lot of Transforms and serialized data to use templates (aka nested prefabs), load from disk only them and then instantiate them to fill the UI with content

- to reduce the amount of serialized data you can store repeated settings in ScriptableObjects (SO) and make a lot of loaded/instantiated objects to refer to only one SO.



- from version 5.4 the Transforms of the objects on a scene are layed out contiguously in the memory: the root transforms allocate heap memory buffer for a number of transforms and then stores child's transforms in it. Every reparenting (and child index change) becomes less performant because it involves movement of memory arrays to avoid "holes" in root transform contiguous memory

- use Instantiate(GO, Transform) overload to avoid overhead of creating root transform memory buffer

- if you know the number of childs of an object - set Transform.hierarchyCapacity property to allocate the buffer beforehand and avoid multiple reallocations

- be aware of long reparenting in object pool systems

- Transform updates are pricey - each change generates OnTransformChanged internal event which propagates up and down the hierarchy, so try to do only one transform modification each frame. BUT this will be changed with dirty bits implementation (presumably in Unity 5.6, UPD: it's not) and transform modifications will be very cheap

- use "Optimize Game Object" setting in animation import settings to hide unnecessary transforms from hierarchy and reduce transform modification overhead (also it allows Unity to reorder data for better multi-threaded usage in animation skinning).



- UI responds poorly to activation/deactivation (all mesh and geometry recalculations appears in OnEnable of all UI components); possible workaround is to disable Canvas component only (and unnecessary MonoBehaviours to avoid Update calls) - the UI won't be drawn, no component will be marked as dirty

- UI extensively suffers from method call overheads, so the less components used - the better

- Canvas component tires to batch all it's childs for performance reasons, so any change of any children Drawable component will cause batch recalculations (depth sort involved) which are very expensive; thus good practice is to split (nest) Canvases and/or extract frequently changed canvas elements to separate (maybe nested) Canvas

- all UI always are transparent geometry, no occlusion performed

- reduce a number of RaycastTargets to make UI more responsive.


Some additional best practices from Unity are presented here:[1]


Link 1:

This article in social networks: