Articles of 实体系统的

如何构建系统是Enity组件系统,在C ++中

在C ++中创建ECS时,构建系统的好方法是什么? 每个系统应该是一个专门的类的静态函数(这是否在语义上不仅仅是一个全局函数?)或者,系统应该是相关组件或“系统管理器”的静态方法? 还是有一些更优雅的方式? (这些方法对我来说都不是很优雅…)

实体 – 组件体系结构中的中央逻辑

我已经建立了一个基于entity-component-system-idea的架构。 所以我得到了 组件 – 只需存储数据 系统 – 在组件上运行 脚本 – 只是脚本types的对象并附加到ScriptComponent。 一个ScriptSystem将在脚本上执行init()和update()函数。 然而,我不知道在哪里放置中央游戏逻辑,因为我必须检查一些关于整个游戏过程的东西,拿着地图,计算点数,检查点数是否足够用于结束屏幕等等… … 我应该创建一个附有这样一个脚本的单一实体,还是有更好的解决scheme呢?

在基于组件的devise中实现“游戏逻辑”在哪里?

我一直在试图让我的头脑使用一个实体组件系统的游戏。 但是我正在努力去理解我应该怎样做“游戏逻辑”。 我到目前为止: 组件基本上只是愚蠢的数据持有者,除了getter和setter之外没有任何逻辑。 系统在组件上进行处理。 例如,PhysicsSystem可能会处理包含Transform和Velocity组件的所有实体。 实体只是整数。 我的问题是,如何添加“特定于实体”或“游戏”逻辑? 例如,我将有一个代表玩家的实体。 我如何去移动玩家实体? 夫妇的想法,我不知道有没有好的? 创建一个使用组件的“MovementSystem”(例如PlayerMovementComponent)。 然后给我的玩家实体PlayerMovementComponent。 这基本上只是一个只处理一个实体的系统…似乎是一个很大的巧合。 创建一个包含std::function (或者可能引用一个lua脚本)的脚本或者行为组件,然后可以使用允许独特的游戏逻辑被赋予实体的lambdas。 这似乎违背了我试图遵循的数据导向的方法? 创建一个Player类,让它引用实体Id,然后给玩家类一个挂钩到游戏循环的更新方法。 此更新方法可以在系统进程之前编辑其引用的实体组件。 这基本上完全脱离了ECS的游戏逻辑…不是这个想法的粉丝(也将使我的游戏循环膨胀,因为需要更多独特的实体)。 希望我能对上述三个想法和我可以追求的一些新的想法或想法做一些评论。

我的发动机概念是好的吗?

我目前正在为我的游戏写一个通用引擎。 我已经开发了几个游戏,但从来没有相同的“基地”,我的代码是相当混乱。 这个想法是创造一个引擎,我可以使用任何types的游戏。 我已阅读关于实体/组件管理器的文件。 有些人正在使用他们所谓的节点,系统等……我认为这有点混乱,特别是节点的概念。 我打算不使用节点,我的问题基本上是:“这是一个很好的引擎概念”吗? 如果不是,我可以做些什么改进? 首先,我游戏中的所有元素都是实体。 玩家是一个实体,任何地图的瓦片或任何实体。 一个实体(在我的引擎中)是一个具有位置的基本类和一个组件列表。 在我看来,所有的“特征”,“行为”等都必须通过组件来实现。 实体类也将有一个更新和一个渲染方法。 该实体拥有一个独特的特殊组件,该组件是实现接口“Renderable”的组件,将处理实体的渲染,不需要渲染的实体将不具有渲染组件。 这是为了实体,现在是关于组件。 目前在我的引擎中,一个组件是给实体带来某些东西的东西。 例如,如果我希望我的实体可以通过键盘或其他方法进行控制,那么我将添加一个处理这个实体的组件。 在引擎更新过程中,实体管理器将更新其所有实体,每个实体将更新其所有组件(或至less需要更新的组件)。 class KeyboardControllComponent extends AbstractComponent implements Updatable { @override public void update() { //do the input handling here } 基本上这个组件会调用另外一个(移动组件),这个移动组件将实际上将运动应用到实体。 另外,我已经实现了我所谓的“调度员”到我的引擎。 它允许游戏中的所有元素(我的游戏中的所有内容都扩展到GameElement类)来分派或侦听事件。 例如,如果英雄走过一个特定的事物(例如陷阱),则负责英雄实体移动/碰撞的组件将向所有正在监听这类事件的游戏元素发射事件。 我将以一个灭绝的例子,英雄'碰撞'这个灭火器,负责碰撞的灭火部分,然后向代表某个门的实体发射一个事件并打开它。 这是一个好概念吗? 最后,所有的游戏元素都由经理来处理。 EntityManager,DispatcherManager,SceneManager等… 让我知道你对我的方法有什么看法。 我没有添加实际的代码使用引擎不超载的职位,但如果你想看到它,没有问题。

在组件实体系统中查看多个世界中的一个?

我一直在做空间模拟游戏。 玩家可以控制一艘船,通过虫洞飞行,从一个太阳系到另一个太阳系。 我希望玩家能够在不同的太阳能系统(世界,工厂,防御等)之间切换摄像机视图。 如果我只使用一个组件实体世界,那么我该如何告诉渲染系统寻找精灵组件来只绘制一个太阳系的精灵组件? 我可以为每个精灵组件添加一个“太阳系ID”字段,并让渲染系统在渲染之前检查每个组件,以确保它在“有效”太阳系中。 这似乎不是一个好主意,但。 主要是因为在处理每个精灵之前,我会添加另外一个case(至less其他的组件可能需要类似的检查)。 我可以让渲染系统维护一个内部映射哪个太阳系包含哪些实体,但是我必须编写实体系统来跟踪所有实体,这是我的实体系统框架的工作(Artemis for Java)。 目前我正在计划让所有的太阳能系统彼此分离。 它们不会存在于相同的坐标系中。 我想我可以把所有的东西都放在同一个坐标系上,然后根据玩家想要查看的太阳系来移动相机。 问题在于,我的精灵渲染系统仍然会循环游戏中的所有精灵,而不是仅仅在主动太阳系中。 所以,由于缺乏更好的select,我倾向于使用多个组件实体世界。 所以每个太阳系都会有自己的一套系统(包括渲染系统),并且我会设置哪一个太阳系是活跃的,以便为这个太阳系提供渲染系统。 我不想采取这种方法有两个原因。 首先,它增加了另一层复杂性的一切。 其次,似乎可能会减less循环所有相同types的组件并运行相同的实体系统algorithm的一些性能优势(caching)。 不是在所有组件中进行宽度优先循环,而是通过所有系统组件的深度优先循环。 那么处理这个问题的最好方法是什么?

谁处理基于组件的实体系统中的碰撞

我对当前的plattformer原型进行了类似的学习,以学习基于组件的实体系统模式。 我有CollisionComponent和CollisionSystem。 CollisionSystem检查每个帧与CollisionComponents的所有实体的交集。 然后在CollisionComponent里面标记与这个实体冲突的实体。 因此,如果一个实体A与实体B碰撞,那么它们在CollisionComponent内部都有另一个作为参考的数据。 这工作绝对好,我可以告诉哪个实体与某人/某人碰撞。 现在我有问题如何正确使用这些信息。 我有一个MovementSystem,它根据速度和加速度移动一个MovementComponent实体。 谁现在负责不移动实体或在碰撞时做其他事情。 如果MovementSystem检查实体是否有CollisionComponent,并且运动系统是否应该处理NOT运动? 假设我有这种情况。 我有一个拥有MovementComponent的实体(玩家),右边的速度(因为玩家按下右箭头),以及由于重力影响而产生的通常的向下速度。 玩家实体与另一个实体冲突。 一个GroundComponent实体。 现在哪个系统应该使实体A(玩家)向上,以便他不再与地面发生碰撞? 运动系统? 与此同时,玩家实体与另一个实体 – 敌人相撞。 现在哪个系统应该处理这个伤害,还是击退敌人对玩家单位的任何伤害? 我真的很喜欢CBES,但是实际上并没有想到如何将所有东西粘合在一起。 我想威胁组件作为纯粹的数据,所以没有逻辑(除了ScriptComponents,但这是另一种types的问题) 现在我的问题是,哪个系统处理哪些情况以及如何处理系统的通行证(例如,移动通过一个然后其他系统然后移动通过2等等?我真正需要多less个系统,并且如果系统只处理一种问题?MovementSystem – >纯粹的运动不管是什么CollisionSystem – >纯粹的碰撞登记不管是什么,DamageSystem – >基于组件数据的损坏处理

基于组件的实体系统中的字符状态

我正在开发类似Zelda的游戏( github ),并且我制作了一个基于组件的实体系统。 我有一个Scene类,其中包含SceneObject的std::vector 。 SceneObject是组件的集合 Scene使用系统,如MovementSystem , DrawingSystem , CollisionSystem来执行使用组件的操作,或者直接使用组件本身。 例如,这是MovementSystem : #include "CollisionComponent.hpp" #include "MovementComponent.hpp" #include "MovementSystem.hpp" #include "PositionComponent.hpp" void MovementSystem::process(SceneObject &object) { if(object.has<PositionComponent>() && object.has<MovementComponent>()) { auto &positionComponent = object.get<PositionComponent>(); auto &movementComponent = object.get<MovementComponent>(); movementComponent.movement->process(object); movementComponent.isBlocked = false; if(object.has<CollisionComponent>()) { object.get<CollisionComponent>().checkCollisions(object); } movementComponent.isMoving = (movementComponent.vx || movementComponent.vy) ? true : false; positionComponent.move(movementComponent.vx […]

在哪里存储连续的组件数组?

我一直在研究一个实体组件系统,并且不知道在哪里定义/放置每个组件types的数组。 每个组件types都是用户定义的,所以我不知道要创建多less个数组,所以我猜测我需要使用模板来做些什么。 这是我迄今为止所做的例子用法。 我很困惑,不确定我到目前为止所做的是如何去做的。 template<class T> class Component { public: Component() = default; virtual ~Component() {}; private: friend class Entity; uint64 m_entity_id; static std::vector<T> COMPONENTS; }; 示例组件: class Velocity : public Component<Velocity> { public: ~Velocity(); float get_x() const; float get_y() const; private: float x; float y; }; 这个想法是,这将为每个组件types创建一个静态数组。 这感觉像是一个奇怪的方式来实现我的目标,但我想不出其他任何方式。 我错过了这个问题的一个明显的解决办法?

如何处理实体/组件系统中的循环依赖关系?

我建立了一个标准的C ++实体/组件系统,有点像这个问题 )。 组件可以通过其关联的Entity访问其他组件。 这通常是通过在组件初始化期间获取某种引用/指针来完成的。 例如,一个Jetpack组件可以访问一个RigidBody组件,并使用它来对该实体施加强制。 在一个场景中组件可以被移除,但是大多数情况下它们不能。 像Renderer , PhysicsEngine和InputManager这样的子系统每个都监听特定types的组件,并在每一帧中处理它们。 这些组件应该如何互相访问? 我看到几个解决scheme,但没有好的。 这些是潜在的解决scheme: 生指针:快,但违反了RAII的想法。 如何检查组件是否被释放? 这感觉就像一条不安全的道路。 shared_ptr :这似乎工作相当安全。 由于参考计数,我可以忍受它有点慢的事实; 指针通常只在初始化期间设置,无论如何。 循环引用呢? 如果两个组件互相引用,它们将永远不会被释放。 这可以通过手动清除某些Component::terminate()的shared_ptr来解决,这是在组件从场景中移除时调用的。 手动清理的想法似乎打破了首先使用智能指针的目的。 此外,确保terminate()在正确的时间被调用会增加复杂性,因为我不能使用析构函数 – 由于循环引用,它永远不会被调用。 shared_ptr和weak_ptr :在内部,在引擎中,组件被存储为shared_ptr ; 但外部(即组件)只能得到weak_ptr 。 这里的缺点是所有组件在每次访问另一个组件时都必须调用weak_ptr::lock() ,这可能是每个框架的几次。 对于使用已知存在于整个场景中的组件的组件也是如此,因此不需要存在检查。 与shared_ptr解决scheme相反,这种性能损失是每帧发生的,而不是仅在初始化时发生。 也许这是值得的,但它似乎笨拙,可能非常缓慢。 避免直接访问:通过在各个组件之间添加一个间接级别,通过某种types的消息系统,循环依赖问题可能永远不会出现。 我没有尝试过,因为它似乎过于复杂。 这可能过于复杂吗? 避免循环迭代:我不太清楚怎么做,但也许你可以完全禁止循环shared_ptr ,以某种方式。 这些解决scheme的不足之处是否可以弥补,还是有更好的方法来处理实体/组件系统中的周期性依赖关系?

我应该在所有项目中实施实体组件系统吗?

我不是在这里要求任何特定的代码实现,我只是为了使我的想法更清晰。 但让我解释一下情况: 我已经开发了一些小型和非常规的游戏项目(从未发布过),但是最近我发现了一些关于ECS的有趣的文章,我开始阅读更多关于它的内容。 我发现每个有趣的整个ECS概念,我想我可以在我空闲时间的一个非常小的游戏中实现它。 问题是:我应该在一个简单的游戏机制和糟糕的游戏性的小项目上实现这个模式吗? 我正在开发的2D游戏将完全由我开发,所以实际上我并不需要让代码更容易被其他人所利用。 这个游戏基本上只有2个玩家,一些武器和各种子弹和超级大国。 没有IA的敌人,没有车辆,静态和微小的地图和..只是。 当然,它只有一个简单的物理系统(例如,让玩家掉落和子弹移动),以及由玩家编辑(瓦片)的平铺但非常小的地图。 所以问题是:为什么我应该为这样一个基本的游戏写一个ECS呢? 考虑到游戏devise,我真的有真正的优势吗? 我的意思是,我知道这样做是非常好的,即使将来你的代码也是非常灵活和容易维护的,但是我也知道这个模式是为了避免一些限制和旧的分层结构提供的代码重复而发明的,据我所知,这个游戏并没有很宽的层次结构。 我开始编写它,但是我发现了一些方面,说实话,吓到我了。 就像所有的组件都通过它们的所有者(他们所绑定的实体)的引用相互交谈,据我所知,避免caching未命中是不好的。 最后一件事是,我觉得我不会写超过两个相同types的组件,这会使得ECS的用处不大。 我知道我并没有把整个ECS的概念真正清楚,顺便说一句,这是我第一次实施它,但是我希望你能明白我的问题。