什么是 Unity 新的面向数据的技术堆栈 (DOTS)

如果我们看看过去十年计算和游戏的发展,我们就会发现与十年前相比有何不同。然而,最重大的变化之一是从一个 90% 的代码在单个内核的单个线程上运行的世界,转变为一个我们每个人的口袋里都有数百个 GPU 内核的世界,我们必须设计高效代码可以并行运行。如果我们看看这种变化,我们就可以想象为什么 Unity 会感到适应这种新范式的冲动。Unity最初的设计诞生于不同的时代,现在是时候适应未来了。面向数据的技术栈(DOTS) 是 Unity 试图以更快、更轻、更重要的是针对当前大规模多线程世界进行优化的方式重塑其内部架构的统称。

在本文中,我们将了解 DOTS 的三个主要组件以及它如何帮助您开发下一代游戏。

想了解更多 Unity 优化技巧?

Unity 引擎带有一组强大的功能,可帮助您构建高性能游戏。如果您想了解编写更好的游戏脚本的技巧,并了解如何使用 Unity 技术(例如 ECS 和 Burst 编译器)优化游戏,请阅读由 Chris Dickinson 和 Davide Aversa 博士撰写的《Unity 游戏优化 – 第三版》一书。本书将帮助您快速了解一系列提高性能的编码技术和方法,这些技术和方法将帮助您提高 Unity 应用程序的性能。

面向数据的技术栈

三个组件组成了面向数据的技术堆栈:

  1. 实体组件系统(ECS
  2. # 作业系统
  3. 突发编译

让我们看看它们。

实体组件系统 (ECS)

如果您了解 Unity,就会知道两个基本结构代表游戏的每个部分:GameObject 和 MonoBehavior。每个 GameObject 都包含一个或多个 MonoBehavior,MonoBehavior 依次描述场景中每个元素的数据(对象知道什么)和行为(对象做什么)。

GameObject 和 MonoBehavior 在 Unity 的最初几年运行良好;然而,随着多线程编程的兴起,GameObject 架构的许多问题开始变得更加明显。

首先,GameObject 是一个又大又重的数据结构。理论上,它应该只是 MonoBehavior 实例的容器。相反,在实践中,它存在大量问题。举几个例子:

  1.  每个游戏对象都有一个名称和一个 ID。
  2.  每个游戏对象都有一个指向本机 C++ 代码的 C# 包装对象
  3. 创建和删除 GameObject 需要锁定和编辑全局列表(即这些操作不能并行运行)。

而且,GameObject和MonoBehavior都是动态对象,在内存中无处不在。如果我们能让一个 GameObject 的所有 MonoBehavior 彼此靠近,这样查找和运行它们会更有效率,那就更好了。

为了解决所有这些问题,Unity 引入了实体组件系统 (ECS),这是一种替代传统 GameObject/MonoBehavior 的新范例。

顾名思义,ECS 包含三个要素:

  1. 组件:它们在概念上类似于 MonoBehavior,但它们只包含数据。例如,一个 Position 组件将只包含一个表示实体在空间中位置的 3D 矢量;LinearVelocity 组件将仅包含对象的速度,等等。它们只是普通数据。
  2. 实体:它们只是组件的“集合”。例如,如果我在空间中有一个粒子,我可以只用组件列表来表示它,例如 Position 和 LinearVelocity 组件。
  3. 系统:系统就是行为所在。每个系统都有一个组件列表,并对原型组件组成的所有实体执行一个函数。

[box type=”shadow” align=”” class=”” width=””]从技术上讲,实体不是集合数据结构。相反,它是指向内存中存储实体组件的位置的指针。不过,实际存储是由 Unity 处理的。[/box]

使用这个系统,我们可以将组件存储到连续的数组中,实体只是指向原型实例的指针。每个系统的单一功能可以定义数千个相似实体的行为。这比在每个 GameObject 中的每个 MonoBehavior 上运行更新更有效。

出于这个原因,借助 ECS,我们可以使用实体而不会出现任何减速或系统开销,而这在 GameObject 实例中是不可能的。例如,粒子系统的每个粒子都有一个实体。

C# 作业系统

如果 ECS 是我们描述场景的方式,我们需要一种有效运行系统的方法。正如我们在介绍中所说,提高效率的现代方法是利用我们系统中的每个核心,这意味着使用大规模多线程系统并行运行代码。

可悲的是,多线程很难。极难。任何有经验的开发人员都会告诉您,从单线程编程转向多线程编程会引入一大类新问题和错误,例如竞争条件。此外,对于真正的多线程,我们应该尽可能接近金属,避免 C# 和垃圾收集器的所有动态分配和释放以及我们游戏中的 C++ 代码部分。

对我们来说幸运的是,Unity 在面向数据的技术堆栈中引入了一个组件,其特定目的是仅使用 C# 简化 Unity 中的多线程编程:作业系统

您可以将 Job 想象成一段代码,您希望它在尽可能多的内核上并行运行。Unity C# 作业系统可帮助您设计此代码,避免所有仅使用 C# 的常见多线程陷阱。您终于可以在不编写一行 C++ 代码的情况下释放机器的所有功能。

突发编译器

如果我告诉您可以通过编写 C# 代码而不是 C++ 来获得更高的性能呢?你会认为我疯了。然而,我不是,这就是面向数据技术堆栈 (DOTS) 的最后一个组件的目标:Burst 编译器。

Burst 编译器是一种专门的代码生成器,可将 C# 的一个子集(通常称为高性能 C# 或 HPC#)编译成机器代码,在大多数情况下,该代码比等效的 C++ 生成的代码更小、更快代码。

Burst 编译器仍处于预览阶段,但您已经可以使用 Unity 的包管理器试用它。当然,当与其他两个 DOTS 组件结合使用时,您可以从中获得最大收益。

未经允许不得转载:Unity3D » 什么是 Unity 新的面向数据的技术堆栈 (DOTS)

赞 (1)