本文意在总结unity程序集的使用方法和精简结论
一.程序集概述
概念:Unity中,程序集(Assembly)是C#代码的编译单元,它将相关的脚本分组在一起
存放位置:Library\ScriptAssemblies

作用:优化项目编译速度、控制代码耦合度、控制代码针对平台编译
默认情况下,Unity 将几乎所有C#脚本编译到预定义程序集Assembly-CSharp.dll中
这种安排对于小型项目来说是可以接受的,但当您向项目添加更多代码时,就会有一些缺点:
- 每次更改一个脚本时,Unity 都必须重新编译所有其他脚本,从而增加迭代代码更改的总体编译时间。
- 任何脚本都可以直接访问任何其他脚本中定义的类型,这会使重构和改进代码变得更加困难。
- 所有脚本均针对所有平台进行编译。
二.查找脚本所属的程序集
选中脚本,在Inspector中Assembly Information部分

三.程序集定义文件(.asmdef)
程序集定义文件是用于程序集设计规划的文件,不是程序集(.dll)文件
通过Create->Assembly Definition可创建程序集定义文件(.asmdef)


.asmdef所在文件夹及其子文件夹(除非子文件夹有自己的程序集定义)中的所有脚本都会被编译到这个新程序集中

创建.asmdef后unity会立刻编译生成.dll文件:

四.引用规则
4.1 访问另一个程序集中的类,其所在的程序集必须对另一个程序集引用
脚本TestA属于程序集:AsmTestA

脚本Test属于程序集:AsmTest, 若要访问TestA

AsmTest需要引用AsmTestA:

添加引用后一定要点Apply
4.2 程序集不可相互引用
程序集的引用必须是单向的,不可A引用B后,B再引用A,否则会报错:

4.3 默认情况下,预定义程序集 引用 所有自定义程序集
自定义程序集:

预定义程序集中的代码对其访问:

没有报错
4.4 自动引用属性用来控制自定义程序集是否被预定义程序集引用
默认Auto Referenced属性是勾选的,这代表预定义程序集会自动引用该自定义程序集
取消勾选后,再改动一下代码比如加一个分号,触发重新编译,可以验证自定义程序集中的类不可访问了:

4.5 自定义程序集不可引用预定义程序集
选择引用的程序集的时候,没有预定义程序集,只有自定义程序集和预编译程序集

五.程序集引用文件(.asmref)
程序集引用文件作用:当一个文件夹中的脚本不想创建新程序集,而是希望归属于其他位置的某个已有程序集时,可以创建程序集引用文件。


为asmref文件指定归属的程序集定义文件:

脚本的归属程序集已改变:

六.区分程序集类型
理清预定义程序集、预编译程序集、自定义程序集十分重要:
| 程序集类别 | 定义与来源 | 典型例子 | 能否被自定义程序集引用? |
|---|---|---|---|
| 预定义程序集 | Unity 自动 将未使用 .asmdef 管理的脚本编译成的程序集 |
Assembly-CSharp.dll (主游戏代码) Assembly-CSharp-Editor.dll (编辑器代码) |
不能 (官方文档明确禁止) |
| 预编译程序集 | 作为 .dll 文件直接导入项目的第三方库或 Unity 自带的模块 |
UnityEngine.UI.dll |
能 (默认自动引用所有预编译程序集,也可以在 .asmdef 中通过 Override References 手动精确控制) |
| 自定义程序集 | 开发者通过 .asmdef 文件创建的程序集。 |
你自己创建的任何 .asmdef |
能 (需要在 .asmdef 的 Assembly Definition References 中显式添加引用) |
Unity这样设定主要是出于编译依赖和编译效率的考虑。
-
禁止引用"预定义程序集" :预定义程序集(如
Assembly-CSharp.dll)本身就依赖于所有自定义程序集。如果自定义程序集反过来又依赖它,就会形成循环引用,编译器无法处理。 -
允许引用"预编译程序集" :因为这些程序集(如
UnityEngine.UI.dll)是独立编译的,与你代码没有双向依赖关系,所以可被自定义程序集引用。
七.编译关系
修改自定义程序集A后,将A引用的程序集(包括自定义和预编译程序集)也会编译
接下来做几个测试进行论证:

CASE1:改动一个被引用的程序集AsmTestA,将AsmTestA引用的程序集AsmTest和预定义程序集都编译了

CASE2:取消勾选AsmTestA的Auto Referenced选项,改动被引用的程序集AsmTestA,将AsmTestA引用的程序集AsmTest编译了,预定义程序集未编译


CASE3:改动自定义程序集AsmTest(未被其他程序集引用),只有AsmTest和预定义程序集编译了

八.最佳实践
在中大型项目中使用程序集,将所有代码归入自定义程序集,从而避免将任何代码留在Assembly-CSharp.dll中,这样可以获得最佳编译效率


