我应该在游戏中的图形和物理引擎之间共享数据吗?


9

我正在编写包含几个模块的游戏引擎。其中两个是图形引擎物理引擎

我想知道这是否是在他们之间共享数据的好解决方案?

两种方式(是否共享)如下所示:

不共享数据

GraphicsModel{
    //some common for graphics and physics data like position

    //some only graphic data 
    //like textures and detailed model's verticles that physics doesn't need
};

PhysicsModel{
    //some common for graphics and physics data like position

    //some only physics data 
    //usually my physics data contains A LOT more informations than graphics data
}

engine3D->createModel3D(...);
physicsEngine->createModel3D(...);

//connect graphics and physics data 
//e.g. update graphics model's position when physics model's position will change

我看到两个主要问题:

  1. 很多冗余数据(例如物理数据和图形数据的两个位置)
  2. 更新数据的问题(物理数据更改时,我必须手动更新图形数据)

与共享数据

Model{
     //some common for graphics and physics data like position
};

GraphicModel : public Model{
    //some only graphics data 
    //like textures and detailed model's verticles that physics doesn't need
};

PhysicsModel : public Model{
     //some only physics data 
    //usually my physics data contains A LOT more informations than graphics data
}

model = engine3D->createModel3D(...);
physicsEngine->assingModel3D(&model); //will cast to 
//PhysicsModel for it's purposes??

//when physics changes anything (like position) in model 
//(which it treats like PhysicsModel), the position for graphics data 
//will change as well (because it's the same model)

这里的问题:

  1. physicsEngine无法创建新对象,只能从engine3D中“确定”现有对象(以某种方式看来对我来说是反独立的)
  2. 在assingModel3D函数中投射数据
  3. physicsEngine和graphicsEngine必须小心-它们在不需要数据时不能删除数据(因为第二个可能需要它)。但这是罕见的情况。而且,他们只能删除指针,而不能删除对象。或者我们可以假设graphicsEngine将删除对象,physicsEngine只是指向它们的指针。

哪种方法更好?

将来哪些会产生更多问题?

我更喜欢第二种解决方案,但我想知道为什么大多数图形和物理引擎更喜欢第一种(也许是因为它们通常只制作图形或仅物理引擎,并且有人在游戏中将它们联系起来?)。

他们还有其他隐藏的利弊吗?


也是我的问题。
danijar

Answers:


9

如今,越来越多的游戏引擎采用了组件设计(例如Unity,Unreal)。在这种设计中,a GameObject由一系列组件组成。在您的情况下,可以有一个MeshComponent和一个PhysicalComponent都附加到一个游戏对象上。

为简单起见,您可以将世界转换变量放入GameObject。在更新短语期间,PhysicalComponent将世界转换输出到该变量。在渲染期间,MeshComponent读取该变量。

这种设计的基本原理是使组件之间分离。无论是MeshComponent也不PhysicalComponent知道对方。它们仅取决于通用接口。与使用单一继承层次结构相比,按组成部分扩展系统可能更容易。

但是,在实际情况下,您可能需要在物理/图形同步之间进行更复杂的处理。例如,物理模拟可能需要以固定的时间步长(例如30Hz)运行,而渲染则需要可变。您可能需要对物理引擎的输出结果进行插值。不过,某些物理引擎(例如Bullet)直接支持此问题。

Unity为它们的组件提供了很好的参考,值得一看。


这根本不能回答问题,有2个组件并不能说明它们是否共享网格数据。
Maik Semder

2
实际上,它提供了更好的设计,这是完全合法的。
jcora 2012年

7

引擎通常会选择第一个选项(拥有自己的物理网格物体和拥有自己的渲染网格物体),因为它们需要在质量和数量上完全不同的数据。

质量,因为物理引擎不关心纹理坐标,法线组和所有这些花哨的渲染东西。他们每个人都希望数据采用非常特定的布局,最终归结为对齐问题,打包,数据交织等。

数量,因为物理网格通常具有较少的三角形,它是高分辨率渲染网格的简化版本。

通过将两者分离,我们确保我们可以缩短一个星期,包括更改其数据布局以获得更好的性能,而又不破坏另一个。它更具扩展性。


0

除了@Millo Yip很棒的答案外,我想提醒您,您将需要与Controls模块和AI模块共享相同的数据,并且如果我没有记错的话,大多数音频库都具有声音发射器位置的概念因此您也需要与该模块共享数据。


0

就像其他人所说的那样,物理学将内部数据状态与渲染引擎的内部数据状态分开管理是很常见的事情。通常甚至看到与物理和可渲染对象分开存储的变换数据(位置/方向/比例),因为可能存在一个游戏对象,它不是由物理施加的,也不是由渲染的,但是需要其他力学的世界位置。

数据如何从物理变为可渲染完全取决于您。

您可以通过一些使用事件/消息的子系统间调度过程来完成此任务。您可以通过将渲染子系统的公共接口暴露给物理子系统来做到这一点,以便物理可以简单地设置特定的可渲染对象的位置。另一个选择是,可渲染子系统在更新过程中向实体查询转换,并先更新可渲染组件的位置,然后再进行绘制。

自然,根据您的游戏,其中一些手段将比其他手段更易于缓存,并具有更好的性能。在这一点上,我不会因为某种特定的方式而陷入困境,而是选择一种交流方式并尝试一下。您稍后可以轻松地重做此部分,以测试各种优化手段。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.