Fork me on GitHub

DOTS原则和愿景

Unity Data Oriented Tech Stack基于一系列原则。这些原则为我们正在努力实现的目标提供了良好的背景。一些原则清楚地反映在代码中。其他则只是我们为自己设定的目标。

默认情况下的性能

我们希望为所有平台创建高效的机器代码变得简单。

我们使用手写的高度优化的simd内在函数来衡量C ++中可以实现的性能。

我们使用编译器技术(Burst),容器(Unity.Collections),数据布局组件(ECS)的组合,以便在默认情况下轻松编写高效代码。

  • 数据布局和迭代 - 实体组件系统在默认情况下以块的形式迭代实体时保证线性数据布局。这是面向统一数据的技术栈提供性能提升的关键部分。
  • C#作业系统允许您以简单的方式编写多线程代码。这也很安全。C#Job Debugger可以检测任何竞争条件。
  • Burst是我们专门针对C#作业的编译器。C#作业代码遵循我们可用于生成更高效的机器代码的某些模式。使用SIMD指令为每个目标平台编译和优化代码。

这方面的一个例子是Instantiation的性能。与实例化具有320字节memcpy的100,000个实体需要9ms的理论限制相比,通过实体组件系统实例化这些实体需要10ms。所以我们非常接近理论极限。

在Unite Austin,我们在60 FPS的大型战斗模拟中展示了一个包含100,000个独立单元的演示。所有游戏代码都运行多核。 参见ECS性能演示[视频]

简单

编写高性能代码必须简单。我们相信我们可以编写快速代码,就像MonoBehaviour.Update一样简单。

注意:为了正确设定期望,我们认为我们仍有一些方法可以实现这一目标。

编写代码的一种方法

我们想要定义编写游戏代码、编辑器代码、资产管道代码以及引擎代码的单一方式。我们相信这为我们的用户创造了一个更简单的工具,并且更有能力改变现状。

物理学是一个很好的例子。目前物理学是一种黑盒解决方案。在实践中,许多开发人员希望调整模拟代码以适应他们的游戏需求。如果使用ECS以与游戏代码相同的方式编写物理引擎代码,则可以轻松地在现有物理仿真阶段之间插入您自己的仿真代码或完全控制。

另一个例子,让我们想象你想制作一个可以进行大规模修改的游戏。

如果我们的导入管道是作为一组ComponentSystems实现的。我们有一些FBX导入管道代码,默认情况下在资产管道中用于导入和后处理FBX文件。(在编辑器中使用Mesh和FBX导入代码。)

然后,很容易配置程序包管理器,可以在已部署的游戏中使用相同的FBX导入和后处理代码进行修改。

我们相信,在基础层面,这将使Unity比现在更加灵活。

联网

我们想要定义一种编写所有游戏代码的简单方法。遵循此方法,您的游戏可以使用三种网络架构中的一种,具体取决于您创建的游戏类型。

我们专注于为托管游戏提供最佳的网络引擎支持。使用最近收购的Multiplay.com服务,我们提供了一个简单的管道来托管所述游戏。

  • FPS - 服务器上的模拟
  • RTS - 确定性锁步模拟
  • 街机游戏 - GGPO

注意:为了正确设置期望,我们尚未在实体组件系统之上提供任何网络代码。它正在进行中。

确定性

我们的构建管道必须是确定性的。用户可以选择是否所有模拟代码都应该确定性地运行。

无论使用何种设备,您都应该使用相同的输入获得相同的结果。这对于网络,重放功能甚至高级调试工具都很重要。

为此,我们将利用Burst编译器在不同平台之间生成精确的浮点数学运算。想象一下,运行相同浮点数学代码的linux服务器和iOS设备。这对于许多场景非常有用,特别是对于连接的游戏,还有调试,重放等。

注意:浮点数学差异是Unity决定解决的问题。这个问题已经有一段时间了解,但到目前为止还没有足够的需要来鼓励人们解决它。为了解决这个问题,包括避免解决问题所需的一些解决方法,请考虑阅读Bruce Dawson的浮点确定性

沙盒

Unity是一个沙盒,安全而简单。

当错误地使用API​​时,我们提供了很好的错误消息,我们从未将自己置于不正确的使用导致崩溃的位置,这是设计上的(而不是我们可以快速修复的错误)。

沙箱行为的一个很好的例子是我们的C#作业系统保证您的C#作业代码都没有竞争条件。我们通过静态代码分析和运行时检查的组合确定性地检查所有可能的竞争条件。我们会立即为您提供有关任何竞赛条件的错误信息。因此,您可以相信您的代码可以正常工作并且感觉安全,即使是第一次编写多线程游戏代码的开发人员也会做得很好。

极小性

我们希望Unity可用于从<50kb可执行文件,到千兆字节大小的游戏的所有内容。我们希望Unity在不到1秒的时间内加载小内容。

迭代时间

我们的目标是在大型项目文件夹中任何常见操作的迭代时间保持500ms以下。

作为一个例子,我们正在努力将C#编译器重写为完全增量,目标是:

在大型项目中更改单个.cs文件时。组合的编译和热重载时间应小于500毫秒。

我们的代码提供完整的单元测试覆盖率

我们相信从一开始就提供强大的代码。我们使用单元测试来证明我们的代码在开发人员编写和提交时正常工作。测试作为包的一部分提供。

演化

我们知道我们在如何编写代码方面提出了相当大的改变。从MonoBehaviour.Update到ComponentSystem并使用作业。

我们相信,最终唯一可以说服游戏开发者的是尝试它,并亲眼看到自己的游戏结果

因此,在现有项目中应用ECS方法应该容易且快速。我们的目标是在30分钟内,用户可以在大型项目中将一些代码从MonoBehaviour.Update更改为ComponentSystem,并拥有优化游戏代码的成功经验。

我们希望我们的大多数引擎代码都是用C#编写的,并部署在一个Package中。所有Unity Pro客户均可使用所有源代码。

我们希望与客户建立快速反馈循环,因为我们可以推送代码并在包中快速获得反馈,而不会破坏其他部分的稳定性。

以前我们的大多数引擎代码都是用C ++编写的,这与我们的客户编写代码的方式以及Unity的程序员如何编写代码产生了脱节。由于Burst编译器技术和ECS,我们可以用C#代码实现比C ++更好的结果,因此我们都能以完全相同的方式编写代码。

合作

我们相信Unity用户和Unity开发人员都在同一个团队中。我们的目的是帮助所有Unity用户更快,更高质量和更好的性能创建最佳游戏体验。

我们相信,我们开发的每个功能都必须尽早开发真实的场景和真实的生产反馈。包管理器促进了这一点。

对于那些希望贡献引擎代码的社区用户,我们的目标是通过直接处理贡献者可以提交的相同代码存储库来实现这一目标。通过明确的原则和所有功能的全面测试覆盖,我们希望保持高贡献的质量。

源代码存储库将适用于所有Unity Pro客户。

透明度

我们相信透明度。我们公开发展我们的功能,我们在论坛和博客上积极沟通。我们保留时间,以便每个开发人员都可以花时间与客户一起了解用户的痛点。

posted @ 2019-08-08 20:39  gamedev'  阅读(588)  评论(0编辑  收藏  举报