The Unity build process uses a tool called the Unity linker to strip managed code. The Unity linker is a version of the IL Linker customized to work with Unity. The custom Unity Engine specific parts of the Unity linker aren’t publicly available.
The Unity linker is responsible for both managed code stripping and part of the process of engine code stripping, which is a separate process available through the IL2CPPA Unity-developed scripting back-end which you can use as an alternative to Mono when building projects for some platforms. More info
See in Glossary script backend that removes unused engine code. For more information, see PlayerSettings.StripEngineCode].
The Unity linker analyzes all the assemblies in your project. First, it marks root types, methods, properties, and fields. For example, MonoBehaviour-derived classes you add to GameObjectsThe fundamental object in Unity scenes, which can represent characters, props, scenery, cameras, waypoints, and more. A GameObject’s functionality is defined by the Components attached to it. More info
See in Glossary in a SceneA Scene contains the environments and menus of your game. Think of each unique Scene file as a unique level. In each Scene, you place your environments, obstacles, and decorations, essentially designing and building your game in pieces. More info
See in Glossary are root types.
The Unity linker then analyzes the roots it has marked to identify, and marks any managed code that these roots depend upon. Upon completion of this static analysis, any remaining unmarked code is unreachable by any execution path through your application code and the Unity linker deletes it from the assembly.
The Unity Editor creates a list of the assemblies that contain types used in any of the Scenes in your Unity project and passes this list to the Unity linker. The Unity linker then processes those assemblies, any references of those assemblies, any assemblies declared in a link.xml file, and any assemblies with the AlwaysLinkAssembly attribute. In general, the Unity linker doesn’t process assemblies included in your project that don’t fall under one of these categories, and excludes them from the Player build.
For each assembly the Unity linker processes, it follows a set of rules based on the classification of the assembly, whether the assembly contains types used in a Scene, and the Managed Stripping Level you have selected for the build.
For the purpose of these rules, assemblies fall into the following classifications:
When you build a project in Unity, the build process compiles your C# code to a .NET bytecode format called Common Intermediate Language (CIL). Unity packages this CIL byte code into files called assemblies. The .NET framework libraries and any C# libraries in the plugins you use in your project are also pre-packaged as assemblies of CIL bytecode.
When the Unity linker performs its static analysis, it follows sets of rules to determine which parts of the CIL bytecode the Unity linker marks as necessary for the build. Root marking rules determine how the Unity linker identifies and preserves top-level assemblies in the build. Dependency marking rules determine how the Unity linker identifies and preserves any code that the root assemblies depend on.
The Managed Stripping Level property changes the set of rules that the Unity linker uses. The following sections describe the marking rules for each possible setting for the Managed Stripping Level property.
The following table describes how the Unity linker identifies the top-level types in an assembly:
Assembly type: | Marking rules: | ||||
---|---|---|---|---|---|
Minimal | Low | Medium | High | ||
.NET Class & Platform SDK and UnityEngine Assemblies | Applies precautionary preservations and any preservations defined in any link.xml file. | Applies precautionary preservations and any preservations defined in any link.xml file. | Applies any preservations defined in any link.xml file. | Applies any preservations defined in any link.xml file. | |
Assemblies with types referenced in a scene | Marks all types and members in the assembly. | Marks all types and members in the assembly. | Marks the following: •All methods which have the [RuntimeInitializeOnLoadMethod] or [Preserve] attribute.•Preservations defined in any link.xml file. •Marks all types derived from MonoBehaviour and ScriptableObject in precompiled, package, Unity Script or assembly definition assemblies. |
Marks the following: •All methods which have the [RuntimeInitializeOnLoadMethod] or [Preserve] attribute.•Preservations defined in any link.xml file. •Marks all types derived from MonoBehaviour and ScriptableObject in precompiled, package, Unity Script or assembly definition assemblies. |
|
All other | Marks all types and members in the assembly. | Marks the following: •All public types and public members of those types. •All methods which have the [RuntimeInitializeOnLoadMethod] or [Preserve] attribute.•Preservations defined in any link.xml file. •All types derived from MonoBehaviour and ScriptableObject in precompiled, package, Unity Script or assembly definition assemblies. |
Marks the following: •All public types and public members of those types. •All methods which have the [RuntimeInitializeOnLoadMethod] or [Preserve] attribute.•Preservations defined in any link.xml file. •All types derived from MonoBehaviour and ScriptableObject in precompiled, package, Unity Script or assembly definition assemblies. |
Marks the following: •All methods which have the [RuntimeInitializeOnLoadMethod] or [Preserve] attribute.•Preservations defined in any link.xml file. •All types derived from MonoBehaviour and ScriptableObject in precompiled, package, Unity Script or assembly definition assemblies. |
|
Test | Marks any methods with the [UnityTest] attribute and any methods annotated with an Attribute defined in the NUnit.Framework. |
After the Unity linker identifies the roots in an assembly, it needs to identify any code that those roots depend on. The following table describes how the Unity linker identifies dependencies of root types in an assembly:
Rule Target | Action at each stripping level | ||||
---|---|---|---|---|---|
Minimal | Low | Medium | High | ||
MonoBehaviour | The Unity linker marks all members of a MonoBehavior type when it marks the type. | ||||
ScriptableObject | The Unity linker marks all members of a ScriptableObject type when it marks the type. | ||||
Attributes | When the Unity linker marks an assembly, type or other code structure, it also marks all attributes of those structures. | When the Unity linker marks an assembly, type or other code structure, it also marks all attributes of those structures. | When the Unity linker marks an assembly, type or other code structure, it only marks attributes of those structures if the attribute type is also marked. | When the Unity linker marks an assembly, type or other code structure, it only marks attributes of those structures if the attribute type is also marked. | |
Debugging Attributes | When script debugging is enabled, the Unity linker marks all members that have the [DebuggerDisplay] attribute, even when there isn’t a code path that uses those members. |
When script debugging is enabled, the Unity linker marks all members that have the [DebuggerDisplay] attribute, even when there isn’t a code path that uses those members. |
The Unity linker always removes debugging attributes such as DebuggerDisplayAttribute and DebuggerTypeProxyAttribute. | The Unity linker always removes debugging attributes such as DebuggerDisplayAttribute and DebuggerTypeProxyAttribute. | |
.NET Facade Class Library | Removes facade assemblies since they aren’t necessary at runtime. |
Link.xml files support an uncommonly used “features” XML attribute. In the example, the mscorlib.xml file embedded in mscorlib.dll uses this attribute, but you can use it in any link.xml file, when appropriate.
When you use the High stripping level, the Unity linker excludes preservations for features that aren’t supported based on the settings for the current build:
For example, the following link.xml file preserves one method of a type on platforms that support COM, and one method on all platforms:
<linker>
<assembly fullname="Foo">
<type fullname="Type1">
<!--Preserve FeatureOne on platforms that support COM-->
<method signature="System.Void FeatureOne()" feature="com"/>
<!--Preserve FeatureTwo on all platforms-->
<method signature="System.Void FeatureTwo()"/>
</type>
</assembly>
</linker>
When you use the High stripping level, the Unity linker edits method bodies to further reduce code size. This section summarizes some of the notable edits that the Unity linker makes to method bodies.
The Unity linker only edits method bodies in the .NET Class Library assemblies. After method body editing, the source code of the assembly no longer matches the compiled code in the assembly, which can make debugging more difficult.
The following list describes actions that the Unity linker can perform to edit a method body: