Unity预定义程序集及自定义包编译顺序
在Unity项目中,unity会按照脚本在项目中的位置生成四个预定义程序集(Assembly-CSharp-firstpass
,Assembly-CSharp-Editor-firstpass
,Assembly-CSharp
,Assembly-CSharp-Editor
),其编译顺序是按插件->工程代码,运行时->Editor规则交错的编译顺序.
对于Package的代码,Package中的代码不能依赖于预定义程序集,只能依赖于Unity插件!所谓插件指的是编译成dll或平台对应的库文件.
- #### 特殊文件夹和脚本编译顺序
- #### 预定义的程序集
- #### 默认引用
- #### 程序集定义和包
- #### 注意事项
- #### 程序集定义 (Assembly Definition) 属性
- Name and General
- Define Constraints
- 无效或不兼容的约束
- Assembly Definition References
- Assembly References
特殊文件夹和脚本编译顺序
Unity 保留了一些项目文件夹名称来指示内容具有特殊用途。其中一些文件夹会影响脚本编译的顺序。这些文件夹名称为:
- Assets
- Editor
- Editor default resources
- Gizmos
- Plugins
- Resources
- Standard Assets
- StreamingAssets
请参阅特殊文件夹名称了解有关这些文件夹的更多信息。
预定义的程序集
Unity 根据脚本文件在项目文件夹结构中的位置,以四个不同的阶段编译脚本。Unity 为每个阶段创建一个单独的 CSharp 项目文件 (.csproj) 和一个预定义的程序集。(如果没有符合编译阶段的脚本,Unity 不会创建相应的项目文件或程序集。)
当脚本引用在不同阶段编译的类(因此位于不同的程序集中)时,编译顺序很重要。基本规则是无法引用在当前阶段_之后_的阶段编译的任何内容。在当前阶段或早期阶段编译的所有内容则是完全可用的。
编译阶段如下:
阶段 | 程序集名称 | 脚本文件 |
---|---|---|
1 | Assembly-CSharp-firstpass | 名为 Standard Assets、Pro Standard Assets 和 Plugins 的文件夹中的运行时脚本。 |
2 | Assembly-CSharp-Editor-firstpass | 名为 Editor 的文件夹(位于名为 Standard Assets、Pro Standard Assets 和 Plugins 的顶级文件夹中的任意位置)中的 Editor 脚本。 |
3 | Assembly-CSharp | 不在名为 Editor 的文件夹中的所有其他脚本。 |
4 | Assembly-CSharp-Editor | 其余所有脚本(位于名为 Editor 的文件夹中的脚本)。 |
注意:Standard Assets 仅在 Assets 根文件夹中有效。
您可以创建程序集定义文件,从而使用自己的程序集来组织项目中的脚本。定义自己的程序集可以减少在进行不相关的代码更改时需要重新编译的代码量,并可提供对其他程序集的依赖性的更多控制。请参阅脚本编译 - 程序集定义文件以了解更多信息。
默认引用
默认情况下,预定义程序集会引用所有其他程序集,包括使用程序集定义创建的程序集 (1) 以及作为插件添加到项目中的预编译程序集 (2)。此外,使用程序集定义资源创建的程序集会自动引用所有预编译程序集 (3):
默认设置中,预定义程序集中的类可以使用项目中任何其他程序集定义的所有类型。同样,使用程序集定义资源创建的程序集可以使用在任何预编译(插件)程序集中定义的所有类型。
可以通过在程序集定义资源的 Inspector 中关闭 [Auto Referenced 选项]来防止预定义程序集引用某个程序集。关闭自动引用意味着在更改程序集中的代码时不会重新编译预定义程序集,但也意味着预定义程序集无法直接使用此程序集中的代码。请参阅[程序集定义 (Assembly Definition) 属性]。
同样,可以通过在插件资源的 [Plugin Inspector] 中关闭 [Auto Referenced 属性]来防止自动引用插件程序集。这会影响预定义程序集以及使用程序集定义创建的程序集。请参阅 [Plugin Inspector] 以了解更多信息。
关闭插件的 Auto Referenced 时,可以在 Inspector 中为程序集定义资源显式引用它。请启用该资源的 [Override References] 选项,然后添加对插件的引用。请参阅[程序集定义 (Assembly Definition) 属性]。
注意 :无法声明预编译程序集的显式引用。预定义程序集只能使用自动引用的程序集中的代码。
程序集定义和包
必须将包内的脚本与程序集定义文件 (.asmdef
) 关联。在 Unity 中,程序集定义文件等效于 .NET 生态系统中的 C# 项目。必须在程序集定义文件中设置对其他程序集(无论是在同一包中还是在外部包中)的显式引用。请参阅程序集定义以了解更多详细信息。
请使用以下约定来命名和存储程序集定义文件,确保编译的程序集文件名遵循 .NET Framework 设计指南 (.NET Framework Design Guidelines):
-
将特定于 Editor 的代码存储在根 Editor 程序集定义文件中:
Editor/MyCompany.MyFeature.Editor.asmdef
-
将特定于运行时的代码存储在根运行时程序集定义文件中:
Runtime/MyCompany.MyFeature.Runtime.asmdef
-
为 Editor 和运行时脚本配置相关的测试程序集:
Tests/Editor/MyCompany.MyFeature.Editor.Tests.asmdef
Tests/Runtime/MyCompany.MyFeature.Runtime.Tests.asmdef
要整体了解建议的包文件夹布局,请参阅自定义包布局。
注意事项
- 注意程序集的meta文件中保存了程序集中monobehaviour事件的执行顺序,所以删除meta重新会导致脚本执行顺序变动.
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
相关参考链接:
特殊文件夹名称
程序集定义和包
程序集定义
程序集定义 (Assembly Definition) 属性
自定义包布局
程序集定义 (Assembly Definition) 属性
Name and General
属性 | 描述 |
---|---|
名称 | 程序集的名称(不含文件扩展名)。程序集名称在整个项目中必须唯一。请考虑使用 reverse-DNS 命名样式降低名称冲突的风险,尤其是希望在多个项目中使用该程序集的情况下。 注意:Unity 会将您分配给程序集定义资源的名称用作 Name 字段的默认值,但您可以根据需要更改此名称。但是,如果您通过名称而不是 GUID 来引用程序集定义,则更改名称将使引用无效。 |
Allow ‘unsafe’ code | 如果在程序集内的脚本中使用了 C# unsafe 关键字,请启用 Allow ‘unsafe’ Code 选项。启用此设置后,Unity 在编译程序集时会将 /unsafe 选项传递到 C# 编译器。 |
Auto Referenced | 指定预定义的程序集是否应引用此项目程序集。禁用 Auto Reference 选项后,Unity 不会在编译过程中自动引用该程序集。这不会影响 Unity 是否将文件包含在构建中。 |
No Engine References | 启用此属性后,Unity 在编译程序集时不会添加对 UnityEditor 或 UnityEngine 的引用。 |
Override References | 启用 Override References 设置可以手动指定此程序集依赖哪些预编译的程序集。启用 Override References 后,Inspector 会显示 Assembly References 部分,在此部分中可以指定引用。 预编译的程序集是在 Unity 项目外编译的库。默认情况下,在项目中定义的程序集将会引用添加到项目中的所有预编译程序集,这一点与预定义程序集引用所有预编译程序集的方式一致。启用 Override References 后,此程序集仅引用您在 Assembly References 下添加的预编译程序集。注意:为了防止项目程序集自动引用预编译程序集,可以禁用 Auto Referenced 选项。请参阅 Plugin Inspector 以了解更多信息。 |
根命名空间 | 此程序集定义中脚本的默认命名空间。如果您使用 Rider 或 Visual Studio 作为您的代码编辑器,它们会自动将此命名空间添加到您在此程序集定义中创建的任何新脚本中。 |
请参阅[创建程序集定义资源]。
Define Constraints
指定编译器 #define 指令;必须定义这些指令,才能让 Unity 编译或引用程序集。
Unity 仅在已满足 Define Constraints 中的所有约束条件时才会编译和引用项目程序集。约束的作用与 C# 中的 #if 预处理器指令类似,但在程序集级别(而不是脚本级别)运行。您必须定义 Define Constraints 设置中的所有符号,才能满足这些约束。
要表示必须取消定义某个符号,请在该符号前面添加否定!
(叹号)符号作为前缀。例如,如果在 Define Constraints 中指定以下符号:
!ENABLE_IL2CPP
UNITY_2018_3_OR_NEWER
当符号 ENABLE_IL2CPP 未定义且符号 UNITY_2018_3_OR_NEWER 已定义时,则满足这些约束。换言之,仅在 Unity 2018.3 或更高版本的非 IL2CPP 脚本运行时中,Unity 才编译和引用此程序集。
可以使用 ||
(OR) 运算符来指定必须存在至少一个约束才能满足这些约束条件。例如:
UNITY_IOS || UNITY_EDITOR_OSX
UNITY_2019_3_OR_NEWER
!UNITY_ANDROID
例如:UNITY_IOS 或 UNITY_EDITOR_OSX 已定义且 UNITY_2019_3_OR_NEWER UNITY_ANDROID 未定义时满足约束。各行类似于在约束之间执行逻辑 AND。以上示例等同于:
(UNITY_IOS OR UNITY_EDITOR_OSX) AND (UNITY_2019_3_OR_NEWER) AND (NOT UNITY_ANDROID)
可以使用 Unity 的任何内置 #define 指令、全局编译器响应文件 (.rsp) 定义的符号,以及项目的 Scripting Define Symbols Player 设置中定义的任何符号。请参阅[平台相关的编译]以了解更多信息(包括内置符号的列表)。
注意: Scripting Define Symbols 设置与具体平台有关。如果使用此设置来定义 Unity 是否应使用程序集,请务必定义所有相关平台上的必要符号。
请参阅[有条件地包含一个程序集]。
无效或不兼容的约束
Unity 根据当前定义的设置使用指示器标记每个约束。例如,以下这两个约束指示当前一个符号有定义,而另一个未定义。由于要满足整体约束条件,每个单独的约束条件都必须为真,因此 Define Constraints 框也被标记为无效或不兼容。
为了满足本示例中的约束,您可以将 Scripting Backend 更改为 IL2CPP(位于 Player Settings 中)。但是,通常重要的是构建项目时如何评估约束,而不是约束在 Unity 编辑器中的显示方式。例如,您可能有一个程序集,您只想将其包含在使用 IL2CPP 后端的构建中,而不包含在使用 Mono 后端的其他构建中。
Assembly Definition References
属性 | 描述 |
---|---|
Assembly Definition References | 指定对使用程序集定义资源创建的其他程序集的引用。Unity 使用这些引用来编译程序集,还定义程序集之间的依赖关系。 |
Use GUIDs | 此设置控制 Unity 如何序列化对其他程序集定义资源的引用。启用此属性后,Unity 将这些引用另存为资源的 GUID,而不是程序集定义的名称。最好是使用 GUID 而不是名称,因为这意味着可以更改程序集定义资源的名称,而不必更新引用该程序集的其他程序集定义文件。 |
请参阅[创建程序集定义资源]。
Assembly References
Assembly References 部分仅在您启用 Override References 属性(位于 [General] 部分)时出现。使用这一区域可以指定对此程序集依赖的预编译程序集的任何引用。
请参阅[引用预编译的插件程序集]
技术有限,如有纰漏,请在回复中指出.