1 2 3 4 5 6 7 8 9 10

【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特有的,但在其他开发环境中也有类似的概念。
例如:

  1. .NET Framework和.NET Core:在这些平台上,开发者可以使用csproj文件来定义项目和其依赖关系。通过合理配置项目,可以实现类似于Unity中的程序集管理。
  2. Java:在Java中,JAR文件相当于程序集,开发者可以使用构建工具(如Maven或Gradle)来管理项目的模块化和依赖关系。
  3. C++:在C++中,开发者可以通过使用静态库和动态库来实现模块化,但这需要手动管理依赖关系和编译过程。

1.3 默认划分

在Assets文件夹中编写脚本,如果没有进行自定义操作,会默认编译到 Assembly-CSharp.dll 中。
简单来说,我们正常编写的脚本会被划分为Assembly-CSharp程序集中。
image
这里也能说明当前这个脚本是隶属于哪个程序集中的。

在Editor目录下的脚本文件会被自动分为Assembly-CSharp-Editor程序集。
image

更多类似默认划分的还有:

  1. Plugins目录:Assembly-CSharp-firstpass
  2. Plugins目录下的Editor目录:Assembly-CSharp-Editor-firstpass

1.4 程序集之间的引用

如果程序集A引用了程序集B,而程序集B又引用了程序集C,那么程序集A可以间接访问程序集C中公开的类型。
以下是默认程序集的引用关系。
image
即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文件。
image
创建完成后,当前目录下的所有脚本将会被划分为一个独立的程序集

2.2 介绍

image

  1. name:不允许重复。

  2. Allow unsafe code:如果程序集中使用了Unsafe关键字,需要勾选此选项,否则报错。

  3. Auto Referenced:指定是否所有预定义程序集都应引用此程序集。
    例如所有不带ASMDEF的脚本(比如在Assets/Scripts目录下的普通C#脚本)会自动引用Assembly-Common。
    这使得这些脚本能够访问Assembly-Common中的代码。

  4. No Engine References:启用后该程序集的脚本将无法访问MonoBehaviour等Unity程序集里的代码。

  5. Override References:启用后以手动方式确认需要引用哪些程序集。

  6. Root NameSpace:默认的命名空间。

  7. Define Constraints:指定必须定义的编译器#define指令,才能编译或引用程序集。

  8. Assembly Definition References:指定对使用AssemblyDefienitions创建的其他程序集的引用。
    即为该AssemblyDefinition程序集添加其他AssemblyDefinition程序集的引用,通过拖拽的方式即可。
    image
    如上图,此时qwe程序集能够访问到abs程序集的代码

参考文章:

Unity关于程序集(Assembly )的那些事
Unity中的程序集(Assembly)

posted @   mayoyi  阅读(406)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示