This blog covers some Tips and Tricks on memory optimization and working with textures and was compiled by Steve Hughes who works as an Applications Engineer for Visual Computing at Intel. For more information see Steve and Cristiano's article (most of the tips are applicable to Windows as well as Android) and my Tips for using Unity with the Intel® RealSense™ SDK.
Working with Textures
- Don't create Mipmaps for textures unless really needed
- Use compressed textures
- Don't set textures to readable (CPU R/W) except when needed. This avoids extra CPU copies, markers, etc.
- Reduce the size of textures depending on screen resolution
- Android & Small Screens:
- On models - skip the top MIP (Quality Settings>Rendering>Texture Quality)
- Separate RGB (compressable) from Alpha (non compressable) channels
- Normal maps don’t need to be 1:1 scale with diffuse maps.
- Remove redundant keyframes from animations (only refresh to change graphic)
For Mesh Models
- Remove unused channels from meshes (under Player settings, enable Optimized Mesh Data)
- For high detail meshes on low RAM systems, set Quality to use maxLOD
For more information for optimizing graphics in Unity, see: How To Plan Optimizations with Unity
- Make use of the 200k buffer for audio playback
- Load short clips uncompressed into this buffer
- Or use AudioClip.GetData to uncompress, and then free the compressed one
- Two methods to see what's consuming RAM
- Profiler.GetRuntimeMemorySize() can find high RAM consuming objects (suggest output to debug log)
- Look in Mono's CIL (Common Intermediate Language) for the 3 alloc types - Newarr, Newobj, Box
- Manually expand the heap by pre-allocating memory space at startup (based on a history of assets usages.)
- For on the fly needs, call Resources.UnloadAsset (if asset still needs to be referenced) or use Resources.UnloadUnusedAssets (for non referenced)
- Since Unity's Auto Garbage Collection is usually only called when the heap is full or there is not a large enough freeblock, consider calling (System.GC..Collect) before and after loading a level (or put it on a timer) or otherwise cleanup at transition times.
- Avoid functions with large amounts of hidden allocs
- Avoid memory fragmentation by using structures (stored on stack) instead of classes (stored on heap).
- Remember enumerators allocate RAM. And (Foreach) is reprocessed into a block of code which allocates an enumerator, too.
- For the same reason, avoid Anonymous methods and Lambdas.
- Stream assets to consume less RAM, Collect related assets into Asset Bundles at build and then stream them out at run time. (Be sure to destroy them before the next scene or asset bundle stream).
- Don’t add strings together. Don’t manipulate strings per frame (instead add a trap so you only update if it changes value.)
- Use the StringBuilder class to make strings, Don't use an array into a function that returns a string because it will keep dumping and re-allocating each time in the loop
- Create asset pool classes (bullets/missles) to store objects instead of multiple new-ing - such as
MyClass m – poolOfMyClass //do stuff poolOfMyClass.Store(m);
CREDITS: Parts of the above material were collected from:
- Memory resources on Unity3.com
- Andrew Frey - Reducing Memory Usage In UNITY, C# AND .NET/MONO
- Gamasutra: C# Memory Management for Unity Developers (part 1 of 3)
For additional information, see:
- https://software.intel.com/en-us/node/542152 (most of the tips are applicable to Windows as well as Android)
- Tips for using Unity with the Intel® RealSense™ SDK.
For more such intel resources and tools from Intel, please visit the Intel® Developer Zone