Version: 2019.1
特殊文件夹和脚本编译顺序
托管代码剥离

程序集定义

Create Assembly Definitions to organize the scripts in your project into assemblies. When you create an Assembly Definition Asset in a folder, Unity compiles a separate managed assembly from all the scripts in that folder. (Scripts in subfolders are included unless the subfolder has its own Assembly Definition.) You can think of each of these managed assemblies as a single library within your Unity Project.

An Assembly Definition Asset is a text file, with a file extension of “.asmdef”, that contains a JSON string defining the Assembly Definition properties. You can set these properties in a Unity Inspector window by selecting the asset file. You can also edit the JSON directly using an external editor. See Assembly Definition File format for information about the JSON syntax.

Why use Assembly Definitions

When you separate your code into assemblies having well-defined dependencies, Unity reduces compilation time by only rebuilding the dependent assemblies when you make a change to a script. Assembly Definitions can also help you manage dependencies in projects containing platform and Unity-version-specific code.

Without Assembly Definitions, Unity compiles any C# scripts in your project into one of the predefined, managed assemblies. Unity must recompile every script in the entire project when you change any script. This means that the length of time between making a code change and seeing that change in action grows longer as you add more scripts to the project.

Note: Although not strictly required, Unity recommends that whenever you use Assembly Definitions in a project, you do so for all of the code in your project. Otherwise, when you change scripts in one of the predefined assemblies, Unity must still recompile all the code in your project, since the predefined assemblies automatically depend upon any assemblies you create using an Assembly Definition.

下图说明了如何将一个项目拆分为多个程序集:

预定义的程序集与手动定义的程序集
预定义的程序集与手动定义的程序集

By default, Unity compiles almost all project scripts into the Assembly-CSharp.dll managed assembly. The above example shows a project divided up into five separate assemblies instead. The Main.dll assembly depends on Stuff.dll and ThirdParty.dll. Stuff.dll depends on Library.dll, and so on. As a result, Unity doesn’t need to recompile any of the other assemblies because of a change to code in Main.dll. And since Main.dll contains fewer scripts, it compiles faster than Assembly-CSharp.dll. Similarly, if code in Stuff.dll changes, Unity only needs to recompile Main.dll and Stuff.dll, not ThirdParty.dll or Library.dll.

Note: You can find out where Unity compiles a particular C# file by selecting the script file in the Project window and looking at the Assembly Information listing in the Inspector:

Assembly-CSharp-Editor.dll 预定义程序集内的脚本
Assembly-CSharp-Editor.dll 预定义程序集内的脚本

How to use Assembly Definitions

Add Assembly Definition Assets to folders in a Unity Project in order to define an assembly. After compilation, the assembly contains all the scripts in the folder and its subfolders (unless the subfolders have their own Assembly Definitions). Set the name of the assembly in the Inspector.

程序集定义是一种 Unity 资源类型。可在 Project 窗口中选择现有的程序集定义来查看或更改其属性。请参阅文件格式以了解关于程序集定义资源文件格式的信息。

要创建程序集定义资源,请执行以下操作:

In the Project window, select the folder in which you want to place the Assembly Definition.

  1. Create the Assembly Definition Asset using the menu: Assets > Create > Assembly Definition.
  2. Select the new Assembly Definition you created.
  3. Set the properties in the Inspector window, as necessary.

You can only create one Assembly Definition per folder. If you create an Assembly Definition in a subfolder of a folder that already has an Assembly Definition, then Unity compiles any scripts in the subfolder and its children into the assembly defined in the subfolder, not the assembly defined in the parent folder.

Version defines

Use Version Defines to handle dependencies between different Resources and Packages in your current Project. This is useful if you want to share your Project through a Package Manager package or an Asset Store package.

To set a version, click the plus sign (+). You can add as many version defines to an Assembly Definition as you want. To delete a define, select it in the list, and click the minus sign (-).

When you add at version define, the following properties appear:

This is what Version defines look like in the Inspector. In this example, there are two active Version defines.
This is what Version defines look like in the Inspector. In this example, there are two active Version defines.
属性 描述
Resource Use this drop-down list to select the Package or Module you want to set a define for. The list contains all active Packages and Modules in the Project.
Define The name you want this define to have. This define is only set if the expression below returns true.
Expression 所选择的模块或包的语义版本范围。必须使用数学间隔符号。不支持通配符。此版本范围与 Microsoft 的 .NET 包管理器(即 NuGet)相同。
Expression outcome 显示 Expression 表示的数学方程式。

Assembly Definition properties

单击程序集定义资源 (Assembly Definition Asset) 可以在 Inspector 窗口中设置程序集的属性。

程序集定义 (Assembly Definition) Inspector
程序集定义 (Assembly Definition) Inspector

Name

The name for the assembly (without a file extension). Assembly names must be unique across the project. Consider using a reverse-dns naming style, especially when an assembly could be used in more than one project. Note that Unity uses the name you assign to the Assembly Definition Asset as the default value of the Name field, but you can change the name as desired.

General

Allow ‘unsafe’ Code

Enable the Allow ‘unsafe’ Code option if you use the C# unsafe keyword in a script within the assembly. When checked, Unity passes the /unsafe option to the C# compiler when compiling the assembly.

Auto Referenced

Specify whether all the predefined assemblies should reference this Project assembly. When checked, the predefined assemblies reference all assemblies defined in the Project, which matches how precompiled assemblies (plugins) are referenced by predefined assemblies.

Override References

Enable the Override References option to manually specify which precompiled assemblies this assembly depends upon. When you enable Override References, the Inspector shows the Assembly References section, which allows you to specify the references.

A precompiled assembly is a library compiled outside your Unity project. By default, assemblies defined in your Project reference all the precompiled assemblies you add to the project, which matches how the predefined assemblies reference all precompiled assemblies. When you enable Override References, this assembly only references the precompiled assemblies you add under Assembly References.

Note, to prevent a precompiled assembly from being automatically referenced by Project assemblies, you can disable its Auto Referenced option. See Plugin Inspector for more information.

Define Constraints

Specify the compiler #define directives that must be defined in order for an assembly to be compiled or referenced.

Unity only compiles and references a Project assembly if all the Define Constraints are satisfied. Constraints work like the #if preprocessor directive in C#, but on the assembly level instead of the script level. All the symbols in the Define Constraints setting must be defined for the constraints to be satisfied. You can also specify that a symbol must be undefined by prefixing it with a negating ! (bang) symbol. For example, if you specify the following symbols as your Define Constraints:

!ENABLE_IL2CPP 
UNITY_2018_3_OR_NEWER

the constraints are satisfied when the symbol ENABLE_IL2CPP is NOT defined and the symbol UNITY_2018_3_OR_NEWER IS defined. Or to put it differently, this assembly is only compiled and referenced on non-IL2CPP scripting runtimes for Unity 2018.3 or newer.

You can use any of Unity’s built-in #define directives or any symbols defined in the project’s Scripting Define Symbols Player setting. See Platform dependent compilation for more information, including a list of the built-in symbols. Note that the Scripting Define Symbols settings are platform-specific. If you use this setting to define whether an assembly is used, make sure that you define the necessary symbols on all the relevant platforms.

Assembly Definition References

Specify references to other assemblies that you have created using Assembly Definition Assets.

Unity uses these references to compile the assembly and also define the dependencies between assemblies.

The Use GUIDs option controls how Unity serializes references to other Assembly Definition Assets. When Use GUIDs is enabled, Unity saves the reference as the Asset’s GUID, instead of the Assembly Definition name. It’s good practice to use the GUID instead of the name, because it means you can make changes to the name of an Assembly Definition Asset without having to update other Assembly Definition files that reference it.

Assembly References

Specify references to any precompiled assemblies on which this assembly depends. You must check the Override References option in the General section to manually specify references to precompiled assemblies.

Unity References

To mark the assembly as a test assembly, enable the Test Assemblies option in the Inspector. Enabling Test Assemblies adds references to the unit.framework.dll and UnityEngine.TestRunner.dll libraries to the Assembly Definition.

When you mark an assembly as a test assembly, predefined assemblies (such as Assembly-CSharp.dll) do not automatically reference this assembly and the assembly is not included in builds.

To include test assemblies in a player build, use BuildOption.IncludeTestAssemblies in your build script.

Note: This option only includes the assemblies in your build and does not execute any tests.

Platforms

设置程序集的平台兼容性。Unity 仅在包含(或不排除)的平台上编译或引用此程序集。

向后兼容性和隐式依赖关系

To maintain compatibility with the existing Predefined Compilation System in Unity, the predefined assemblies reference every assembly you create with an Assembly Definition Asset. This is similar to how the predefined assemblies reference all the precompiled assemblies (plugins / .dlls) in the Project that are compatible with the active build target.

下图说明了预定义的程序集、使用程序集定义资源创建的程序集以及预编译的程序集之间的默认依赖关系。

图 3 - 程序集依赖关系
图 3 - 程序集依赖关系

图中的数字表示程序集之间的引用,可以按以下方式进行控制:

  1. By default, assemblies created with Assembly Definition Assets are referenced by the predefined assemblies. You can turn this off by unchecking the Auto Referenced option in the Inspector for an Assembly Definition Asset. See Assembly Definition properties.

  2. Likewise, precompiled assemblies (plugins) are automatically referenced by both the predefined assemblies and assemblies created with Assembly Definition Assets. You can turn this default behavior off by unchecking the Auto Referenced option in the Inspector for the plugin. See Plugin Inspector.

  3. When you turn off Auto Referenced for a plugin, you can explicitly reference it in the Inspector for an Assembly Definition Asset. Enable the Asset’s Override References option and add a reference to the plugin. See Assembly Definition properties.

Note: if you turn off the Auto Referenced option for precompiled assemblies or assemblies created with Assembly Definition Assets, then classes in the precompiled assemblies can no longer reference or use the classes in these assemblies. You cannot declare explicit references for the precompiled assemblies.

Special Folders

Unity treats scripts in folders with certain, special names differently than scripts in other folders. However, one of these folders loses its special treatment when you create an Assembly Definition Asset inside it or in a folder above it. You are most likely to notice this change in special treatment when you use Editor folders, which can often be scattered throughout your project (depending on how you organize your code and on the Asset packages you use).

Unity normally compiles any scripts in folders named “Editor” into the predefined Assembly-CSharp-Editor assembly no matter where those scripts are located. However, if you create an Assembly Definition Asset in a folder that has an Editor folder underneath it, Unity no longer puts those Editor scripts into the predefined Editor assembly. Instead, they go into the new assembly created by your Assembly Definition — where they probably don’t belong. To handle Editor folders, you can take one of the following approaches:

  • 将程序集定义资源添加到每个受影响的 Editor 文件夹,并设置该程序集的 Platform 属性,以便仅用于 Editor 平台
  • 将所有特定于 Editor 的代码移到程序集定义未涵盖的中心位置。

Test Assemblies

Test assemblies contain code that tests other code in your project. As such, they don’t need to be included in release builds of your project and other, non-test assemblies should not depend on them. You can designate that Unity build a test assembly by checking the Test Assemblies option in the Assembly Definition Asset properties. Setting this property does the following:

  • Prevents the predefined assemblies from referencing the test assembly
  • Excludes the test assembly from builds
  • Adds a reference to the NUnit assembly

Note: Use BuildOption.IncludeTestAssemblies in your building script to include a testing assembly in a Release or Development build. This only includes the assemblies in your build and does not execute any tests.

API

使用 UnityEditor.Compilation 命名空间中的 CompilationPipeline 类可获取 Unity 为项目构建的所有程序集(包括基于程序集定义资源创建的程序集)的相关信息。

例如,以下脚本使用 CompilationPipeline 来列出项目中的所有当前播放器程序集:

using UnityEditor;
using UnityEditor.Compilation;

public static class AssemblyLister
{

    [MenuItem("Tools/List Player Assemblies in Console")]
    public static void PrintAssemblyNames()

    {
        UnityEngine.Debug.Log("== Player Assemblies ==");
        Assembly[] playerAssemblies = 
            CompilationPipeline.GetAssemblies(AssembliesType.Player);

        foreach (var assembly in playerAssemblies)
        {
            UnityEngine.Debug.Log(assembly.name);
        }
    }
}

程序集定义文件格式

Assembly Definition Assets are JSON files. You can edit the Assets inside the Unity Editor or modify the JSON content with an external tool. An Assembly Definition is a JSON object with the following fields:

字段 类型
name string
references(可选) 字符串数组
includePlatforms(可选) 字符串数组
excludePlatforms(可选) 字符串数组
allowUnsafeCode(可选) bool
autoReferenced(可选) bool
overrideReferences(可选) bool
precompiledReferences(可选) 字符串数组
defineConstraints(可选) 字符串数组
optionalUnityReferences(可选) 字符串数组

在同一程序集定义文件中,无法同时使用 includePlatformsexcludePlatforms 字段。

可以使用程序集名称或资源的 GUID 在 references 字段中指定程序集定义资源。要使用资源 GUID,该值应该采用 GUID:Asset GUID 格式,例如,“GUID:0ec2b662ccc592241854c1b507df8a89”。 可使用 AssetDatabase.AssetPathToGUID 来获取资源的 GUID。

可以使用 CompilationPipeline.GetAssemblyDefinitionPlatforms() 函数来获取平台名称字符串。(必须为当前的 Editor 安装对平台的支持。)

程序集定义 JSON 示例

MyLibrary.asmdef

{
    "name": "MyLibrary",
    "references": [ "Utility" ],
    "includePlatforms": ["Android", "iOS"]
}

MyLibrary2.asmdef

{
    "name": "MyLibrary2",
    "references": [ "GUID:0ec2b662ccc592241854c1b507df8a89" ],
     "excludePlatforms": ["WebGL"]
}

  • 2017.3 中的新功能 NewIn20173

  • 在 2018.1 中更新了自定义脚本程序集

  • Additional properties added in 2019.1

特殊文件夹和脚本编译顺序
托管代码剥离