Unity 2017.3 新功能:程序集定义文件
程序集定义文件Assembly Definition File,使用该特性,开发者可以在一个文件夹中自定义托管程序集。定义明晰的依赖文件,可以确保脚本被更改后,只会重新生成必需的程序集,减少编译时间。
开发者的项目越大,编译时间必然会越长。而在进行项目迭代时,这很容易会成为一个问题,因此设置好正确的程序集定义文件可以助力提高工作效率,减少等待脚本编译的时间。
脚本编译—程序集定义文件
Unity自动定义脚本编译为托管程序集的方式。Unity编辑器中进行脚本更改迭代的编译时间会随脚本数量的增加而增加。当然, 在进行迭代时,我们一定是希望编译的速度越快越平顺越好。
你可以使用新的程序集定义文件特性,基于文件夹中的脚本定义你自己的托管程序集。如果你将项目脚本分为多个程序集,并进行良好的依赖定义,可以确保你在更改某个脚本时,只会重新生成必需的程序集。这减少了编译时间,因此你可以在Unity项目中将每个托管程序集看做是单个的库。
(图 01)
图01展示的是可以将项目脚本分为多个程序集。如果你仅仅更改了Main.dll中的脚本,那其它程序集都不需要重新编译。由于Main.dll包含的脚本更少,因此它的编译速度比Assembly-CSharp.dll更快。 同样的,你对Stuff.dll的更改,仅会导致Main.dll和Stuff.dll重新编译。
如何使用程序集定义文件
程序集定义文件是资源文件,可以通过Assets > Create > Assembly Definition菜单创建。它们的扩展名是.asmdef。
你可以将一个程序集定义文件添加到Unity项目中的一个文件夹里,对该文件夹里所有的脚本进行编译,然后在检视窗口中对程序集名称进行设置。
注意:程序集定义文件所在的文件夹名称,以及程序集定义文件的文件名,对程序集的名称毫无影响。
(图 02)
你还可以使用检视窗口添加对项目中其它程序集定义文件的引用。编译程序集和定义程序集间的依赖时会用到这些引用。
Unity使用引用来编译程序集,以及定义程序集之间的依赖关系。你可以在检视窗口中设置程序集定义文件的平台兼容性,也可以选择排除或包括特定平台。
文件夹层级中的多程序集定义文件
如果在一个文件夹层级中,有多个程序集定义文件(扩展名:asmdef),将会使每个脚本被添加到最短路径距离的程序集定义文件中去。
示例
假设你有一个Assets/ExampleFolder/MyLibrary.asmdef和一个Assets/ExampleFolder/ExampleFolder2/Utility.asmdef文件,那么:
Assets > ExampleFolder > ExampleFolder2文件夹中的所有脚本将会被编译到Assets/ExampleFolder/ExampleFolder2/Utility.asmdef定义的程序集中。
Assets > ExampleFolder文件夹中的所有脚本,除Assets > ExampleFolder> ExampleFolder2中的脚本之外,将会被编译到Assets/ExampleFolder/MyLibrary.asmdef定义的程序集中。
程序集定义文件不属于生成系统的文件
注意:程序集定义文件不属于程序集生成文件。它们不支持在生成系统中常见的条件化生成规则。
这也是程序集定义文件不支持预处理指令(定义)的原因,因为它们一直是静态的。
向后兼容与隐式依赖
程序集定义文件向后兼容Unity中现存的[预定义编译系统](Predefined Compilation System)。也就是说,预定义程序集总是依赖于每个程序集定义文件的程序集。这与Unity中所有脚本都依赖于所有和当前生成目标兼容的预编译程序集(插件/.dll)的情况相似。
(图 03)
图3中的图表展示了预定义程序集、程序集定义文件以及预编译程序集之间的依赖关系。
Unity给予程序集定义文件的优先级要比[预定义编译系统](ScriptCompileOrderFolders)高。
这意味着,任何来自程序集定义文件文件夹内的预定义编译的特殊文件夹名,都不会对编译产生任何影响。Unity只将它们视为常规文件夹。
强烈建议你对项目中的所有脚本使用程序集定义文件,或完全不使用。否则,没有使用程序集定义文件的脚本会在每次程序集定义文件重新编译时也被重新编译。这会减少你在项目中程序集定义文件所带来的好处。
API
在UnityEditor.Compilation命名空间中,有一个静态的CompilationPipeline类,你可用它获取程序集定义文件以及所有由Unity生成的程序集的信息。
文件格式
程序集定义文件都是JSON文件。它们有以下这些字段:
字段includePlatforms和 excludePlatforms不能在同一个程序集定义文件中使用。要获取平台名,可使用:
CompilationPipeline.GetAssemblyDefinitionPlatforms
示例
MyLibrary.asmdef
{
"name" : "MyLibrary" ,
"references" : [ "Utility" ],
"includePlatforms" : [ "Android" , "iOS" ]
}
{
"name" : "MyLibrary2" ,
"references" : [ "Utility" ],
"excludePlatforms" : [ "WebGL" ]
}
相关资源
Unity 2017.3 Beta版:
https://unity3d.com/unity/beta
Assembly Definition Files:
https://oc.unity3d.com/index.php/s/xIUxflUSkbcipM8
小结
在等待Unity 2017.3正式发布之前,你可以马上测试这些特性。记得在升级你的项目前先做备份。