我已经开始阅读 Wikipedia 上的资料,但我仍然觉得我并不真正了解场景图的工作原理以及它如何为游戏带来好处。
- 什么是游戏引擎开发上下文中的场景图?
- 为什么我要为我的 2D 游戏引擎实现一个?
- 场景图的使用是否可以替代具有线性实体管理器的经典实体系统?
我已经开始阅读 Wikipedia 上的资料,但我仍然觉得我并不真正了解场景图的工作原理以及它如何为游戏带来好处。
什么是游戏引擎开发上下文中的场景图?
好吧,它是一些代码,可以主动对游戏空间中的游戏对象进行排序,以便于快速找到游戏空间中某个点周围的对象。
这样,很容易:
和其他东西。这是关于允许在空间中快速搜索。它被称为“空间分区”。这是关于分而治之的。
为什么我要为我的 2D 游戏引擎实现一个?
这取决于游戏的类型,更准确地说取决于游戏空间的结构。
例如,像 Zelda 这样的游戏如果速度足以测试屏幕中所有对象之间的碰撞,就不需要这种技术。然而它很容易真的很慢,所以大多数时候你至少设置一个场景图(或任何类型的空间分区)至少知道所有移动对象周围是什么,并只测试这些对象上的碰撞。
所以,这取决于。大多数情况下,出于性能原因需要它。但是你的空间分区的实现完全与你的游戏空间的结构方式有关。
场景图的使用是否可以替代具有线性实体管理器的经典实体系统?
不。
无论您以何种方式管理游戏实体的对象生命,空间分区/场景图仅允许您快速搜索空间中的对象,不多不少。大多数情况下,它会是一个具有一些对象槽的对象,对应于游戏空间的不同部分,并且在这些槽中它将是那些部分中的对象。它可以是平面的(如 2 或 4 中的 2D 屏幕分隔线),也可以是树(如二叉树或四叉树,或任何其他类型的树)或任何其他限制您必须进行的操作数量的排序结构执行以获取一些与空间相关的信息。
注意一件事:
在某些情况下,您甚至需要为不同的目的使用不同的独立空间分区系统。通常,“场景图”是关于渲染的,因此它以取决于玩家视角的方式进行优化,其目的是允许快速收集要渲染的对象列表以发送到显卡。它并不真正适合在另一个对象周围执行对象搜索,这使得它很难用于精确的碰撞检测,例如当您使用物理引擎时。因此,为了提供帮助,您可能有一个不同的空间分区系统,只是为了物理目的。
举个例子,我想做一个“子弹地狱”游戏,其中有很多球需要玩家的飞船以非常精确的方式躲避。为了获得足够的渲染和碰撞检测性能,我需要知道:
所以我递归地将 2D 的屏幕分成 4 个部分,这给了我一个四叉树。四叉树在每个游戏刻更新,因为一切都在不断地移动,所以我必须跟踪四叉树中每个对象(宇宙飞船、子弹、怪物)的位置,以知道哪个对象位于屏幕的哪个部分。
实现 1. 很容易,只需在系统中输入项目符号即可。
为了实现 2。我在屏幕边界上的四叉树(屏幕的平方部分)中保留了一个叶子列表。这些叶子包含靠近边界的子弹的 id/指针,所以我只需要检查它们是否正在移动,以了解我是否可以停止渲染它们并管理碰撞。(它可能有点复杂,但你明白了。)
要实现 3 和 4。我需要检索玩家飞船附近的对象。所以首先我得到了玩家宇宙飞船所在的叶子,然后我得到了里面的所有物体。这样,我只会在周围的物体上测试与玩家飞船的碰撞,而不是所有物体。(它有点复杂,但你明白了。)
这样我就可以确保我的游戏在数以千计的子弹不断移动的情况下也能顺利运行。
在其他类型的空间结构中,需要其他类型的空间划分。通常,卡丁车/汽车游戏会有一个“隧道”场景图,因为玩家在视觉上只会看到沿路的事物,因此您只需检查他在路上的位置即可检索“隧道”周围的所有可见对象.
什么是场景图?场景图包含特定场景的所有几何图形。它们对于表示对象相对于彼此的平移、旋转和缩放(以及其他仿射变换)很有用。
例如,考虑一辆坦克(带有履带和枪的类型)。您的场景可能有多个坦克,但每个坦克的方向和位置都不同,每个坦克的炮塔都旋转到不同的方位角和不同的火炮仰角。您可以在遍历场景图以正确定位它时累积仿射变换,而不是准确地确定每个坦克的枪应如何定位。它使此类事物的计算变得更加容易。
2D 场景图:如果您的内容足够复杂并且您的对象有许多子组件未严格固定在较大的主体上,则使用 2D 场景图可能会很有用。否则,正如其他人所提到的,这可能是矫枉过正。2D 中的仿射变换的复杂性比 3D 的情况要少很多。
线性实体管理器:我不清楚你所说的线性实体管理器到底是什么意思,但如果你指的是跟踪场景中事物的位置,那么场景图可以让事情变得更容易,如果有一个高场景中各种对象或子对象之间的空间依赖程度。
场景图是一种组织环境中所有对象的方式。通常会注意组织数据以进行有效渲染。图表或树,如果你喜欢,可以显示子对象的所有权。例如,在最高层可能有一个城市对象,在它下面会是许多建筑对象,在那些可能是墙壁,家具......
但在大多数情况下,这些仅用于 3D 场景。我建议不要使用 2D 场景复杂的东西。
关于场景图的响应是什么,网络上似乎有很多不同的哲学。人们倾向于放入很多不同的东西,比如几何、相机、光源、游戏触发器等。
一般来说,我会将场景图描述为场景的描述,并且由包含场景中存在的实体的单个或多个数据结构组成。这些数据结构可以是任何类型(数组、树、复合模式等),并且可以描述实体的任何属性或场景中实体之间的任何关系。这些实体可以是任何东西,从实体可绘制对象到碰撞网格、相机和光源。到目前为止,我看到的唯一真正的限制是人们建议保留游戏特定组件(如游戏触发器)以防止以后出现依赖性问题。这些东西必须被抽象为“LogicEntity”、“InvisibleEntity”或只是“Entity”。
以下是场景图中的一些常见用途和数据结构。
您可以在游戏或引擎中使用场景图的方式是描述具有位置的任何事物之间的父/子关系,无论是实体对象、相机还是其他任何事物。这种关系意味着任何孩子的位置、比例和方向都将与其父母的相对。这将允许您使相机跟随玩家或让光源跟随手电筒对象。它还可以让你制作像太阳系这样的东西,你可以在其中描述行星相对于太阳的位置以及卫星相对于它们的行星的位置,如果你正在制作的话。
此外,游戏/引擎中某些系统的特定内容也可以存储在场景图中。例如,作为物理引擎的一部分,您可能已经为实体对象定义了简单的碰撞网格,这些实体对象可能具有过于复杂的几何形状而无法测试碰撞。您可以将这些碰撞网格(我确定它们有另一个名称,但我忘记了:P)放在您的场景图中,并让它们跟随它们建模的对象。
场景图中的另一种可能的数据结构是其他答案中所述的某种形式的空间分区。这将允许您在场景中执行快速查询,例如剪裁不在视锥体中的任何对象或有效过滤掉需要碰撞检查的对象。您还可以允许客户端代码(如果您正在编写引擎)为任何目的执行自定义查询。这样,客户端代码就不必维护自己的空间分区结构。
我希望我能给你和其他读者一些关于如何使用场景图以及你可以在其中放入什么的想法。我敢肯定还有很多其他方法可以使用场景图,但这些都是我想出的。
在实践中,视频游戏中的场景对象很少被组织成一个图形,当场景被渲染时,它就像一棵树一样“行走”。图形系统通常需要渲染一大堆东西,而这个大数组是线性移动的。
需要几何亲子关系的游戏,例如那些拿着枪的人或带有炮塔的坦克,在图形系统之外根据需要定义和强制执行这些关系。这些关系往往只有一层,因此几乎不需要任意深度的树结构。