2 minute read

DISCLAIMER: This document is for my personal use only. I do not take responsibility for the accuracy or reliability of the information contained herein

If you’ve used Unity a lot, you’re probably familiar with the .NET Framework. Unity uses C# for game scripting, which might also mean you have some experience creating C# console games.

C# operates on the .NET architecture. However, it’s important to note that the .NET used in Unity is different from Microsoft’s .NET. This means that programmers need to be proficient in C# and also well-acquainted with the .NET used in Unity, especially if they are engine developers. Understanding this difference is key to managing memory in Unity.

Unity uses two types of .NET: Mono and IL2CPP. The differences are briefly summarized below:

Mono:

Cross-platform like Java Uses Just-In-Time (JIT) compilation Now managed by Microsoft after they acquired Xamarin IL2CPP:

Created to support 64-bit as Mono only supports 32-bit Supports Ahead-Of-Time (AOT) compilation Note that Mono is generally not used in final builds anymore because it only supports 32-bit and performs less efficiently compared to IL2CPP. IL2CPP has the downside of increasing the app’s size due to the AOT method, which can be an issue when managing both time and space resources. However, these memory issues are often addressed with high-performance computers.

The IL2CPP build process can be outlined as follows:

The Roslyn compiler compiles C# code. IL2CPP performs IL stripping to reduce the application’s size. IL2CPP converts IL code into standard C++ code. A C++ compiler compiles the converted C++ code for the target platform. Unity generates executable files or DLLs depending on the target platform. It’s worth noting that code stripping, which automatically deletes unused code, can sometimes introduce bugs unintentionally. For example, when dynamic member variables are used to reference classes (using mechanisms like dynamic binding, lazy evaluation, or reflection), unused members or classes may mistakenly become targets for code stripping. Unity uses C# but does not support all the latest .NET libraries. The supported versions are .NET Standard 2.0 and .NET 4.x, with .NET Standard 2.0 being the recommended version. This is because it supports smaller library sizes, reduces executable file size, and ensures smooth cross-platform support.

Unity’s .NET encompasses three layers of memory management: native memory, managed memory, and unmanaged memory. Each has distinct characteristics for optimal memory management.

Native memory is used internally by the Unity engine and is generally inaccessible to users. If fine-tuning is needed, it can be done indirectly using Unity’s C# API. Unmanaged memory is used for fine-tuning memory allocation accessed by the job system and Burst compiler. For more on these, refer to Unity’s documentation. Managed memory is overseen by the garbage collector, which helps prevent various errors that can occur with memory allocation and deallocation. However, understanding garbage collection is crucial as it can lead to performance degradation if not managed properly. Unity uses a non-generational garbage collection method which does not compact memory, leading to frequent memory fragmentation and potential optimization issues. To minimize performance impact, Unity employs an incremental garbage collection approach.

Categories:

Updated: