【Unity开发】如何使用 Assembly Definition 划分多个程序集,减少编译时间
在Unity开发中,项目的复杂性和规模不断增加,这导致编译时间变得越来越长。
为了提升编译效率,使用Assembly Definition文件(.asmdef)将代码划分成多个程序集是一种非常有效的解决方案。
1. 什么是Assembly Definition?
Assembly Definition是一种Unity用于定义C#程序集的文件。
通过将代码分成多个独立的程序集,Unity可以独立编译这些程序集,而不是每次都编译整个项目。
这不仅可以减少编译时间,还能提高项目的可维护性、可扩展性和模块化。
1.1 程序集的概念
在C#中,程序集是一个逻辑上分隔的代码集合,例如两个不同程序集无法访问对方的类型和成员,除非通过引用建立明确的关系,并确保访问修饰符允许这种访问。
一个程序集通常对应于一个DLL文件或EXE文件。
一个程序集可以包含一个或多个命名空间,而每个命名空间中又可以包含子命名空间或类型列表。
值得注意的是,新版Unity的PackageManager功能则使用了多个程序集,即一个插件就是一个程序集,编译成为一个dll,例如TextMeshPro。
1.2 在其他环境中的类似概念
虽然Assembly Definition是Unity特有的,但在其他开发环境中也有类似的概念。
例如:
- .NET Framework和.NET Core:在这些平台上,开发者可以使用csproj文件来定义项目和其依赖关系。通过合理配置项目,可以实现类似于Unity中的程序集管理。
- Java:在Java中,JAR文件相当于程序集,开发者可以使用构建工具(如Maven或Gradle)来管理项目的模块化和依赖关系。
- C++:在C++中,开发者可以通过使用静态库和动态库来实现模块化,但这需要手动管理依赖关系和编译过程。
1.3 默认划分
在Assets文件夹中编写脚本,如果没有进行自定义操作,会默认编译到 Assembly-CSharp.dll 中。
简单来说,我们正常编写的脚本会被划分为Assembly-CSharp程序集中。
这里也能说明当前这个脚本是隶属于哪个程序集中的。
在Editor目录下的脚本文件会被自动分为Assembly-CSharp-Editor程序集。
更多类似默认划分的还有:
- Plugins目录:Assembly-CSharp-firstpass
- Plugins目录下的Editor目录:Assembly-CSharp-Editor-firstpass
1.4 程序集之间的引用
如果程序集A引用了程序集B,而程序集B又引用了程序集C,那么程序集A可以间接访问程序集C中公开的类型。
以下是默认程序集的引用关系。
即Assembly-CSharp能访问到Plugins内的代码,但是却不能访问到Editor内的代码
如果一个程序集同时引用了A,B两个程序集,而A和B两个程序集又出现了同名的类,此时引用此类将会报错,且无法解决。
1.5 循环依赖
程序集之间的引用是单向的,不在使用A程序集引用B程序集的同时,再使用B程序集去引用A程序集,否则会产生循环依赖。
在C#中,循环依赖是指两个或多个程序集相互引用,导致编译过程中的死循环。
这种情况通常不被允许,因为编译器在编译期间需要确定各个类型和成员的定义,而循环依赖会使得编译器无法完成这项工作。
为什么不能产生循环依赖?
编译机制:
当你修改程序集A中的代码时,程序集A会被重新编译。
若此时,程序集B也引用了程序集A,那么在编译B时,编译器会尝试访问程序集A的定义。
如果B又引用了A,这将导致B需要先编译A,而A又需要依赖B,这样就形成了一个死循环,编译器无法决断哪个程序集应该优先编译。
2. 如何在Unity使用Assembly Definition
2.1 创建
在选中的文件夹上右键单击,选择Create > Assembly Definition。
这将创建一个新的.asmdef文件。
创建完成后,当前目录下的所有脚本将会被划分为一个独立的程序集。
2.2 介绍
-
name:不允许重复。
-
Allow unsafe code:如果程序集中使用了Unsafe关键字,需要勾选此选项,否则报错。
-
Auto Referenced:指定是否所有预定义程序集都应引用此程序集。
例如所有不带ASMDEF的脚本(比如在Assets/Scripts目录下的普通C#脚本)会自动引用Assembly-Common。
这使得这些脚本能够访问Assembly-Common中的代码。 -
No Engine References:启用后该程序集的脚本将无法访问MonoBehaviour等Unity程序集里的代码。
-
Override References:启用后以手动方式确认需要引用哪些程序集。
-
Root NameSpace:默认的命名空间。
-
Define Constraints:指定必须定义的编译器#define指令,才能编译或引用程序集。
-
Assembly Definition References:指定对使用AssemblyDefienitions创建的其他程序集的引用。
即为该AssemblyDefinition程序集添加其他AssemblyDefinition程序集的引用,通过拖拽的方式即可。
如上图,此时qwe程序集能够访问到abs程序集的代码
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!