问题标签 [entity-system]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
entity-system - ECS(实体组件系统)中的交织系统?
我正在为实体系统添加物理特性,但对 ECS 的系统部分感到困惑。
例如,在一个非 ECS 项目中,我可能会有这样的事情:
然而,在 ECS 项目中,我将有一个在 PositionComponent 和 VelocityComponent 上运行的 MovementSystem,以及在 PositionComponent 和 ShapeComponent 上运行的 CollisionSystem。结果是这样的:
不同之处在于,在非 ECS 版本中,运动和碰撞是交错的,而在 ECS 版本中它们是分开的。在实体系统中是否存在对这种行为进行建模的正常模式?我知道 ECS 的全部意义在于摆脱继承,但也许让 MovementSystem 和 CollisionSystem 成为更通用的 PhysicsSystem 的一部分,它在单个实体上调用其他系统更新函数,而不是每个系统都维护自己的循环?
c++ - 减少实体组件系统中的鸭子类型劣势
如何减少实体-组件-系统中的 Duck-typing 现象?
例子
这是一个coliru 演示。
我的 ECS 中有 2 个系统:-
System_Projectile
:管理所有弹丸和子弹方面。
System_Physic
:管理物理组件。
有 2 个组件类型 : Com_Projectile
, Physics
.
有时,我发现在某个组件中缓存指向另一个实体的指针是件好事:-
如果我想改变 的位置Com_Projectile
,我会打电话给manage(Com_Projectile::physic)
。
问题
基于上述代码段的真实程序可以正常工作。
但是,在编码时,Com_Projectile::physic
遭受鸭式打字。
physic
我没有得到关于' 类型的C++ 语义线索。
(变量名和注释除外)因此,我必须意识到这一点。
Coder 对类型的误解只会在运行时被检测到。
但在实践中,这种错误很少发生。我必须回忆起
System_Physic::
可以做我想做的事情的系统名称(),
然后回忆起函数的名称(System_Physic::setVelocity()
在这种情况下)。- 总之,我的大脑有很多间接性。
在我过去,当我使用大量(深度)继承时,它会容易得多,就像这样:-
我真的很怀念列出所有与物理相关的功能的可爱内容助手。
问题
如何减少 ECS 系统某些部分的鸭式打字?
更具体地说,再次启用可爱内容辅助的设计模式是什么?
我目前的解决方法
让Com_Projectile
缓存Physic* physic
而不是Entity*
:-
坏处:-
- 它将促进不需要的(?)耦合。
- 我必须在
Physics
里面转发声明Com_Projectile.h
。 - 我将不得不将复杂的功能(例如
setVelocity()
)从系统(例如Sys_Physic::
)移动到组件(例如Physics::
)中。 - 总的来说,我打破了实体-组件-系统的宗教信仰
->我可能会在某些方面受到惩罚(?)。
game-engine - ECS/CES 共享和依赖组件以及缓存局部性
当存在共享或依赖的组件时,我一直在尝试了解 ECS 的工作方式。我已经阅读了许多关于 ECS 的文章,但似乎无法找到明确的答案。
假设以下场景:
我有一个实体,它有一个 ModelComponent(或 MeshComponent)、一个 PositionComponent 和一个 ParticlesComponent(或 EmitterComponent)。
ModelRenderSystem 需要 ModelComponent 和 PositionComponent。
ParticleRenderSystem 需要 ParticlesComponent 和 PositionComponent。
在 ModelRenderSystem 中,为了缓存效率/局部性,我想遍历紧凑数组中的所有 ModelComponents 并渲染它们,但是对于每个模型,我需要拉出 PositionComponent。我什至还没有开始考虑如何处理每个模型的纹理、着色器等(这肯定会破坏缓存)。
ParticleRenderSystem 的类似问题。我需要 ParticlesComponent 和 PositionComponent,并且我希望能够以缓存有效/友好的方式运行所有 ParticlesComponent。
我考虑让 ModelComponent 和 ParticlesComponent 都有自己的位置,但是每次模型位置变化时都需要同步它们(想象一个角色上的粒子效果)。这增加了另一个需要跟踪和同步组件或值的实体或组件(并可能否定任何缓存效率)。
其他人如何处理这些依赖问题?
c++ - 实体组件系统 - 相互需要的组件
我为我的游戏(C++)编写了一个实体组件系统。然后我重构了我的渲染系统以使用 Entities / RenderComponents 而不是一些虚拟的可绘制界面。它们是一些类,我认为强迫它们成为一个组件没有太大意义。其中一类是地图。
我的地图类由平铺地形类和一些其他数据(不重要)组成。平铺地形类以(目前)TiledTerrainLayer
类的形式管理多个图层。在重构渲染系统之前,我只是继承自该类Drawable
,Transformable
并使该类能够被渲染系统绘制。现在它需要是一个至少有 aTransformComponent
和 some的实体RenderComponent
。
现在,TiledTerrainLayerRenderComponent
应该真的只拥有顶点和纹理的引用,也许还有一个标志是否已经创建。然后,TiledTerrainComponent
他们将拥有瓷砖 indecies 列表以及瓷砖和地图大小。
现在我的问题是,当我设置一个图块时(使用类似SetTile(size_t tileIndex, const Position & pos)
方法的东西,我还必须更新顶点数组的纹理坐标。
我通常对一个需要另一个组件的组件很好。例如,SpriteRenderComponent
需要一个TransformComponent
并且我也可以使用一个组件访问另一个组件的信息。例如,GetBoundingBox() 方法使用变换组件的位置。
我要避免的是两个组件相互“交叉引用”,就像TiledTerrainComponent
(TTC) 和TiledTerrainRenderComponent
. (TTRC)(TTRC 获取 TTC 的 tileIndexList 来创建自己,并且在调用其 SetTile() 方法时,TTC 调用 TTRC 的 UpdateVertices() 方法。
最后,我知道组件应该主要是数据。我只添加了直接获取或修改该数据的方法,例如 SetTile() 或 GetTexture()。在上述情况下,系统是否可行?如果可行,它会是什么样子?
c++ - 实体组件架构:想要拆分大实体 -> 难以重构
在开发的第一步,我设计Car
和AI
作为一个实体。
它工作得很好(伪代码): -
后来,我想要一个新功能:switch in-out Driver(影响AI)。
我拆分实体,如下图所示:-
上面的代码将更新为:-
问题
它在更改前后都运行良好,但很难维护。
如果版本 1 中有N
车辆类型,例如,truck, motercycle, plane, boat, rocket
我
将不得不编辑N*2
可能已经分散在很多地方的行.cpp
。
主要问题:如果我忘记重构任何代码,它仍然可以正常编译。
问题只会出现在运行时。
在现实生活中,每当新设计希望将实体划分为许多更简单的实体时,我都会遇到这样的问题。
重构总是只是添加另一个间接。
问题
假设在version1中,我不希望我想要切换进/出驱动程序。
有没有可能防止这个问题?如何?
c - 设计实体系统时如何避免 C 中的虚函数
我想为我的游戏设计一个实体系统,只使用 C 和一小部分 C++。很多人使用继承来做到这一点,但我偶然发现了标记的联合,并了解到你可以通过这种方式获得类似的结果,因为虚拟函数对于游戏来说很慢(所以我从 Casey Mouratori 和 Jon Blow 那里听说过,我从中画了两个游戏开发者很多灵感)。
Jon Blow 使用尚未发布的新语言 Jai 中的一些特性来避免使用虚函数,所以上面的例子是我唯一的想法。
例如,我可以只编写一个更新函数并使用类型来区分实体。这将是一个非常大的函数,但是嘿,我们避免使用虚函数。
事情是我的游戏包含让我们说士兵和树木。树是静态的,几乎什么都不做,所以我会为树实体编写另一个更轻的结构,以节省一些内存,并使用联合来存储不同类型的树:
我面临的问题是,如果士兵和树木都是可点击的怎么办?如果我使用了继承,我会简单地拥有一个函数 Entity* selectEntity(),然后检查实例类型,但是用我的方法我有点迷路了。
我的方法不好吗?我应该坚持使用虚拟功能还是有办法处理这个问题?