时钟的滴答声:如何在Unity中优化编译时间

上周五标志着​​Unity 5.3.5p7的发布,这是一个不经通知或夸大其词就通过的小补丁。 但是,在此修补程序中,还有一个要点,其中还有许多其他修复措施值得我们关注。

那就对了。 优化您的编译时间又回来了!*升级后,我的编译时间从大约17秒缩短到6.3秒。

*(在Unity 5.2.4之后,大多数版本都有一个编译器错误,该错误会否决最有效的编译时间优化策​​略)

但是,我不仅在这里描述每次更改代码后等待的时间减少10秒有多么惊人,我还想问一个问题:为什么没有更多的人看到这个错误得到修复呢? 减少编译时间的想法会不会激发他人的喜悦?

我唯一的结论是,大多数人没有意识到他们可以优化编译时间。 没有官方文档,并且相关的论坛帖子已经过时,因此要获得全面发展并不容易。 但是一旦有了这些,减少编译时间就很简单,而且好处是巨大的。

因此,这是我与编译时间作斗争的个人策略:

1.了解事实

首先,您需要找出代码编译需要多长时间。 对于我自己的一个人的代码库,它徘徊在17秒左右。 对于较大的团队,合理的估计约为30秒。 为了正确理解这一点,我每小时要进行20到30次更改,而不得不等待30秒而不是6.3秒,这会使我的时间表每小时增加大约10分钟的等待时间

想象一整天加起来多少钱。 整个星期。 每个月。 然后将该数字乘以团队人数。 这不仅仅是浪费时间:更长的编译时间意味着您更容易分心并开始查看电子邮件或Facebook。

但是首先,您需要知道您的编译时间。 而且,您希望始终对其进行跟踪,因此您无需检查任何会大大增加它的内容。 还记得所有浪费的时间吗? 为了解决这个问题,我编写了一个编辑器扩展,您可以在此处从我的Github下载。

2.优化!

在进行优化之前,让我为您提供这一切的工作背景。 更改代码后,Unity会将您的代码重新编译为一个名为Assembly-CSharp.dll(如果您未使用C#编写,则称为Assembly-UnityScript等)的.dll(编译后的代码)。

为了减少重新编译所花费的时间,您可以使用Unity编译成单独的.dll的特殊文件夹,该文件称为Assembly-CSharp-firstpass.dll。 关键部分是如果您不更改此.dll中的代码, 它将不会重新编译 。 这些特殊文件夹分别命名为PluginsStandard Assets,并且必须存在于Assets下的顶级目录中。

注意事项:

  • 由于这些.dll的编译顺序,此firstpass.dll中的代码将无法引用其外部的代码。
  • 更改特殊文件夹中的代码将重新编译.dll并抵消所有优化收益。

考虑到这一点,最优化的最佳选择是不依赖于其他代码并且不太可能更改的代码段。 第三方资产是完美的。 代码库的其他部分也可能需要优化。

但是,我确实发现了简单地将所有第三方资产拖放到Plugins文件夹中的问题。 这些资产中的某些资产依赖于驻留在其原始导入路径中的资源,如果不是这种情况,则会严重破坏。 为了节省时间,我购买了Mad Compile Time Optimizer($ 15)***,因为它可以将非代码文件保留在原处,并且还具有不错的还原功能。

***我没有以任何方式与Mad Compile Time Optimizer关联。

3.看其他嫌疑犯

现在,您的第三方资产已得到优化,您应该看到编译时间大大减少了。 通常这是人们停下来的地方,但仍有几个地方可以检查性能是否有所提高。

[InitializeOnLoad]属性就是这样的一个地方。 对于不熟悉的人,InitializeOnLoad是一个Unity属性,可以将其添加到任何类中,以便在编辑器启动(或编译完成)时调用静态构造函数。 那里任何低效的代码都可能会增加您的编译时间。

经过一些试验,我发现,是的,在InitializeOnLoad期间运行的代码将计入总体编译时间。

为了分析InitializeOnLoad的实例,我用可疑的代码记录了从静态构造器的开始到结束所花费的时间。 大多数InitializeOnLoad实例是无害的(0.0–0.2s),但是我确实遇到了一个滥用该类来加载和缓存资源的类。 我将有问题的代码更改为在需要时懒惰地缓存并继续前进。

最后要检查的是您自己的代码。 是否有未使用的类? 您可能不需要他们在您的项目中花费时间。 我还没有找到记录每个类文件编译时间的好方法,但是根据一般经验,文件大小是复杂性的一个很好的近似值。

可视化是确定哪些文件值得关注的最简单方法。 我之所以使用GrandPerspective(Mac),是因为它可以根据自定义规则过滤结果。 我最终做了一个过滤器,该过滤器与以.cs结尾的名称匹配,并与另一个过滤器匹配,以删除路径包含“插件”或“标准资产”的文件。

这是优化结束时我项目的代码库的外观。 请注意,我的个人代码是更改后唯一的编译代码!

TL; DR:

  • 特殊文件夹在Unity 5.3.5p7中已修复
  • 始终跟踪您的编译时间(Compile Time Tracker)
  • 通过将第三方资产移至资产/插件或资产/标准资产进行优化(我建议使用Mad Compile Time Optimizer)
  • 不要滥用[InitializeOnLoad]