Articles of 实体系统

在基于组件的系统中进行通电

我刚刚开始真正了解基于组件的devise。 我不知道这样做的“正确”方法是什么。 这是场景。 玩家可以装备一个盾牌。 盾牌在玩家周围被画成泡泡,它具有独立的碰撞形状,并且减less了玩家受到区域效应的伤害。 在基于组件的游戏中如何构建这样一个盾牌? 在那里我感到困惑的是,盾显然有三个相关的组件。 损害减less/过滤 精灵 一个对撞机。 更糟的是,不同的盾牌变化可能会有更多的行为,所有这些都可能是组件: 提升玩家最大生命值 健康再生 射弹偏转 等等 我是否在意这个? 盾应该是一个超级组件吗? 我真的觉得这是错误的答案。 所以,如果你认为这是要走的路,请解释。 盾牌应该是自己的跟踪玩家位置的实体吗? 这可能使得难以实施损害过滤。 这也有点模糊附件和实体之间的界限。 屏蔽是否应该是容纳其他组件的组件? 我从来没有见过或听说过这样的事情,但也许这很普遍,我还不够深入。 盾牌是否应该是一套添加到玩家的组件? 可能有一个额外的组件来管理其他组件,例如,这样它们都可以作为一个整体被删除。 (不小心留下了伤害减免部分,现在会很有趣)。 对于具有更多组件体验的人来说,其他东西是显而易见的?

如何在基于组件的实体系统中正确实现消息处理?

我正在实施一个实体系统变体,它具有: 一个实体类只是一个将组件绑定在一起的ID 一堆没有“组件逻辑”的组件类 ,只有数据 一堆系统类 (又名“子系统”,“管理者”)。 这些做所有的实体逻辑处理。 在大多数基本情况下,系统只是通过他们感兴趣的实体列表进行迭代,然后对每个实体进行操作 所有游戏系统共享的MessageChannel类对象 。 每个系统可以订阅特定types的消息来收听,也可以使用该频道向其他系统广播消息 系统消息处理的初始变体是这样的: 依次运行每个游戏系统的更新 如果一个系统对某个组件做了某些事情,而该操作可能对其他系统感兴趣,那么系统会发送一个适当的消息(例如,一个系统调用 messageChannel.Broadcast(new EntityMovedMessage(entity, oldPosition, newPosition)) 每当一个实体被移动) 订阅特定消息的每个系统都获取它的消息处理方法 如果一个系统正在处理一个事件,并且事件处理逻辑需要另一个消息被广播,那么这个消息就会立即被广播,另一个消息处理方法链被调用 这个变种是OK的,直到我开始优化碰撞检测系统(随着实体数量的增加,它变得非常慢)。 起初它只是使用一个简单的蛮力algorithm迭代每个实体对。 然后,我添加了一个“空间索引”,它具有一个单元格网格,用于存储位于特定单元格区域内的实体,从而允许仅对相邻单元格中的实体进行检查。 每次实体移动时,碰撞系统都会检查实体是否与新位置中的某个物体发生碰撞。 如果是,则会检测到碰撞。 如果两个碰撞的实体都是“物理对象”(它们都有RigidBody组件,并且为了不占用相同的空间而相互推开),专门的刚体分离系统会要求移动系统将实体移动到某些具体职位,将他们分开。 这又导致移动系统发送通知关于改变的实体位置的消息。 碰撞检测系统是为了反应,因为它需要更新它的空间索引。 在某些情况下,它会导致一个问题,因为单元格的内容(C#中的实体对象列表)在被迭代时被修改,从而导致迭代器抛出exception。 那么… 如何防止碰撞系统在检查碰撞时被打断? 当然,我可以添加一些“巧妙的”/“棘手的”逻辑,以确保单元格内容得到正确的迭代,但是我认为问题不在于碰撞系统本身(在其他系统中也有类似的问题),而是消息在系统间传递时得到处理。 我需要的是确保特定的事件处理方法在没有任何干扰的情况下完成工作。 我曾经尝试过: 传入消息队列 。 每当某个系统广播一条消息时,该消息就会被添加到对其感兴趣的系统的消息队列中。 当每个帧调用系统更新时,这些消息得到处理。 问题 :如果一个系统A向系统B的队列添加一条消息,如果系统B意味着比系统A更新(在同一游戏帧中) 否则会导致消息处理下一个游戏帧(某些系统不希望) 传出消息队列 。 当一个系统正在处理一个事件时,它所广播的任何消息都会被添加到外发的消息队列中。 消息不需要等待系统更新被处理:它们在初始消息处理程序完成工作之后“马上”处理。 如果处理这些消息导致其他消息被广播,它们也被添加到一个外出队列中,所以所有的消息都被处理在同一个帧中。 问题 :如果实体生命周期系统(我用系统实现了实体生命周期管理)创建一个实体,它会通知一些系统A和B. 当系统A处理消息时,它会导致一连串的消息,最终导致被创建的实体被破坏(例如,一个子弹实体被创建到与某个障碍碰撞的位置,这会导致子弹自毁)。 当消息链正在被parsing时,系统B不会获得实体创建消息。 所以,如果系统B也对实体销毁消息感兴趣,就得到它,只有在“链”parsing完成之后,才会得到初始的实体创建消息。 这导致销毁消息被忽略,创建消息被“接受”,并且整个系统B现在就像实体从未被销毁(访问被删除的实体也会导致exception)一样工作。 编辑 – […]

实体系统如何caching高效?

最近,我一直在阅读大量的实体系统,以在我的C ++ / OpenGL游戏引擎中实现。 我经常听到的关于实体系统的两个关键好处是 由于不需要与复杂的inheritance层次结构纠缠在一起,所以可以轻松地构建新的实体 caching效率,这是我无法理解。 当然这个理论很简单, 每个组件都连续存储在一个内存块中,因此关心该组件的系统可以遍历整个列表,而不必在内存中跳转并杀死caching。 问题是,我不能真正想到这是实际的情况。 首先,我们来看看这些组件是如何存储的,以及它们是如何相互引用的。 系统需要能够使用多个组件,即渲染和物理系统都需要访问变换组件。 我已经看到了一些解决这个问题的可能的实现,而且没有一个能够很好地实现。 您可以让组件存储指向其他组件的指针,或指向存储指向组件的实体的指针。 但是,只要你把指针放入组合中,就已经在杀死caching效率。 您可以确保每个组件数组都是'n'大,其中'n'是系统中存在的实体的数量,但是这种方法可怕地浪费了内存; 这使得向引擎添加新的组件types非常困难,但是仍然会抛弃caching效率,因为您正在从一个arrays跳到另一个arrays。 你可以交错你的实体数组,而不是保持单独的数组,但是你仍然在浪费内存; 使添加新的组件或系统变得过于昂贵,但是现在又增加了使所有旧的级别无效并保存文件的好处。 这一切都假设实体在列表,每帧或时间间隔中线性处理。 事实上,情况并非如此。 假设您使用扇区/门户渲染器或八叉树来执行遮挡剔除。 您可能能够在一个扇区/节点内连续地存储实体,但无论您喜不喜欢,您都会跳来跳去。 那么你有其他的系统,可能更喜欢以其他顺序存储的实体。 AI可能会将实体存储在一个大列表中,直到您开始使用AI LOD; 那么你需要根据玩家的距离或者其他一些LOD指标来分割这个列表。 物理学将要使用八叉树。 脚本不关心,他们需要跑,不管是什么。 我可以看到在“逻辑”(例如ai,脚本等)和“世界”(例如渲染,物理,audio等)之间分开组件,并且分别管理每个列表,但是这些列表仍然必须相互交互。 AI没有意义,如果它不能影响用于实体渲染的变换或animation状态。 实体系统在现实世界的游戏引擎中如何“caching高效”? 也许有一个混合的方法,每个人都在使用,但不是在谈论,比如将实体存储在全局数组中,并在八叉树内引用它。

如何在实体系统中实现function?

在提出两个有关实体系统的问题( 1,2 )之后,阅读一些关于它们的文章 ,我认为我比以前更了解它们。 我仍然有一些不确定性,主要是建立一个粒子发射器,一个input系统和一个摄像头。 我对于实体系统的理解显然还存在一些问题,可能也适用于其他一系列的对象,但我select这三个是因为它们是非常不同的概念,应该涵盖相当宽泛的一面,帮助我理解实体系统以及如何处理像这样的问题,我自己,随着他们的到来。 我使用JavaScript构建了一个引擎,并且实现了大部分的核心function,包括:input处理,灵活的animation系统,粒子发射器,math类和函数,场景处理,相机和渲染,以及一大堆引擎通常支持的其他东西。 我读了Byte56的回答,让我感兴趣的是将引擎变成一个实体系统。 它仍然是HTML5游戏引擎,具有基本的场景哲学,但它应该支持dynamic创建组件的实体。 我现在面临的问题是将我的旧引擎概念融入这个新的编程范例。 以上问题的一些定义已更新: 一个实体是一个标识符。 它没有任何数据,它不是一个对象,它是一个简单的id,代表了所有实体的场景列表中的一个索引(我实际上计划实现它作为组件matrix)。 一个Component是一个数据持有者,但是可以对这些数据进行操作的方法。 最好的例子是一个Vector2D ,或者一个“位置”组件。 它有数据: x和y ,还有一些方法可以使数据操作变得更简单: add() , normalize()等等。 系统是可以在满足一定要求的一组实体上运行的东西; 通常实体需要有一组指定的组件,以便进行操作。 系统是“逻辑”部分,“algorithm”部分,组件提供的所有function纯粹是为了更简单的数据管理。 相机 相机有一个Vector2D位置属性,一个旋转属性和一些围绕一个点的方法。 每一帧,它被送到一个渲染器,连同一个场景,所有的对象都根据它的位置被翻译。 场景然后渲染。 我怎么能在实体系统中表示这种对象呢? 相机是一个实体,组件或组合(按照我的答案 )? 粒子发射器 我用粒子发射器的问题又是什么呢? 我很确定,粒子本身不应该是实体,因为我想支持其中的一万多个实体,我相信创造这么多的实体会对我的performance造成沉重的打击。 我怎么能在实体系统中表示这种对象呢? input管理器 我想谈的最后一个是如何处理input。 在我目前的引擎版本中,有一个叫Input的类。 它是订阅浏览器事件的处理程序,例如按键和鼠标位置更改,并且还保持内部状态。 然后,玩家类有一个react()方法,它接受一个input对象作为参数。 这样做的好处是可以将input对象序列化为.JSON,然后通过networking共享,从而实现平滑的多人模拟。 这如何转化为实体系统?

C ++中的实体/组件系统,如何发现types和构造组件?

我正在使用C ++的实体组件系统,我希望遵循Artemis的风格(http://piemaster.net/2011/07/entity-component-artemis/),因为组件主要是数据包,它是包含逻辑的系统。 我希望利用这种方法的数据中心的优势,并建立一些不错的内容工具。 然而,我遇到的一个驼峰是如何从数据文件中获取一些标识符string或GUID,并使用它来为实体构建组件。 显然我可以有一个大的parsing函数: Component* ParseComponentType(const std::string &typeName) { if (typeName == "RenderComponent") { return new RenderComponent(); } else if (typeName == "TransformComponent") { return new TransformComponent(); } else { return NULL: } } 但这真的很难看。 我打算经常添加和修改组件,并希望构建某种ScriptedComponentComponent,以便您可以在Lua中实现一个组件和系统来进行原型devise。 我希望能够编写一个从某些BaseComponent类inheritance的类,也许可以折腾一些macros使所有的工作,然后让这个类可以在运行时实例化。 在C#和Java中,这将是非常简单的,因为你得到很好的reflectionAPI来查找类和构造函数。 但是,我正在用C ++来做这件事,因为我想提高自己的语言水平。 那么在C ++中如何实现呢? 我已经阅读了关于启用RTTI,但似乎大多数人对此非常谨慎,特别是在我只需要它的一部分对象types的情况下。 如果一个自定义的RTTI系统是我需要的,我可以去哪里开始学习写一个?

在实体组件系统引擎中,如何处理相关实体组?

经过几个游戏devise模式之后,我已经为我的游戏引擎find了实体组件系统(ES System)。 我正在阅读文章(主要是T = Machine ),并查看一些源代码,我想我已经足够了,开始了。 我只有一个基本的想法,我正在努力。 我如何处理彼此依赖的实体组? 让我用一个例子: 假设我正在制作一个标准的头顶射击游戏(想想Jamestown ),我想要构建一个具有多个不同但连接部分的“boss实体”。 分解可能看起来像这样: 船体:运动,渲染 大炮:位置(相对于船体locking),追踪\英雄之火,受伤直到禁用 核心:位置(locking相对于船体),跟踪\英雄的火焰,受到伤害,直到禁用,禁用(呃…摧毁)船队中的所有其他实体 我的目标是将被识别(和操纵)为独特的游戏元素,而不必在每次我想要构建新的聚合元素时重写子系统。 我如何在ES系统中实现这种devise? 我是否实施某种亲子关系(实体可以有孩子)? 这似乎与实体仅仅是空容器并使其感到更多OOP的方法相矛盾。 我是否将它们作为单独的实体来实现,以及某种连接组件(BossComponent)和相关系统(BossSubSystem)? 我不禁想到,这将是很难实施,因为组件沟通似乎是一个大熊陷阱。 我是否将它们作为一个实体来实现,并带有一系列组件(ShipComponent,CannonComponents,CoreComponent)? 这个似乎改变了ES系统的意图(这里的组件似乎太重量实体),但我知道这一点,所以我想我会把它放在那里。 我是否将它们作为我提到的其他东西来实现? 我知道这可以很容易地在OOP中实现,但是我selectES over OOP是我会坚持的。 如果我需要打破纯粹的ES理论来实现这个devise,我会(不喜欢我以前不必妥协纯devise),但是我更愿意为了性能的原因而这样做,而不是从糟糕的devise开始。 对于额外的信用,想想同样的devise,但是,每个“老板实体”实际上连接到由一个主体,主要核心和3个“Boss实体”组成的更大的“BigBoss实体”。 这可以让我看到至less有三个方面的解决scheme(祖父母 – 亲子)…对我来说应该是足够的了。 链接到文章或示例代码将不胜感激。 谢谢你的时间。

实际使用基于组件的实体系统

昨天,我已经阅读了GDC加拿大关于属性/行为实体系统的演示文稿,我觉得它非常棒。 但是,我不确定如何使用它,而不仅仅是理论上。 首先,我会很快向你解释这个系统是如何工作的。 每个游戏实体(游戏对象)由属性 (=可以由行为访问的数据,也可以由外部代码访问)和行为 (=包含OnUpdate()和OnMessage()逻辑)组成。 因此,例如,在Breakout克隆中,每个砖块将由(示例!)组成: PositionAttribute , ColorAttribute , HealthAttribute , RenderableBehaviour , HitBehaviour 。 最后一个可能看起来像这样(这只是一个用C#编写的非工作示例): void OnMessage(Message m) { if (m is CollisionMessage) // CollisionMessage is inherited from Message { Entity otherEntity = m.CollidedWith; // Entity CollisionMessage.CollidedWith if (otherEntity.Type = EntityType.Ball) // Collided with ball { int brickHealth = GetAttribute<int>(Attribute.Health); // owner's […]

实体通信如何工作?

我有两个用户案例: entity_A将如何向entity_A发送一个take-damage消息? entity_A如何查询entity_B的HP? 以下是我到目前为止遇到的情况: 消息队列 entity_A创build一个take-damage消息并将其发送到entity_B的消息队列。 entity_A创build一个query-hp entity_A消息并将其发布到entity_B 。 entity_B创build一个response-hp消息并将其发布到entity_A 。 发布/订阅 entity_B订阅take-damage消息(可能有一些抢先过滤,所以只有相关的消息被传递)。 entity_A产生引用entity_B take-damage消息。 entity_A订阅update-hp消息(可能已过滤)。 每个帧entity_B广播update-hp消息。 信号/插槽 ??? entity_A将update-hp插槽连接到entity_B的update-hp信号。 有什么更好的吗? 我是否正确理解这些通信scheme如何与游戏引擎的实体系统相联系?

“系统”在基于组件的实体架构中的作用是什么?

我一直在阅读很多关于实体组件和系统的知识,并认为实体只是一个ID的想法是相当有趣的。 但是,我不知道这是如何完全与组件方面或系统方面的作品。 组件只是一些相关系统pipe理的数据对象。 碰撞系统使用一些BoundsComponent和一个空间数据结构来确定碰撞是否发生。 到目前为止,所有这一切都很好,但是如果多个系统需要访问相同的组件呢? 数据应该放在哪里? input系统可以修改实体BoundsComponent,但物理系统需要访问与某些渲染系统相同的组件。 另外,实体是如何构build的? 我所读过的很多优点之一是实体build设的灵活性。 系统是否固有地绑定到一个组件上? 如果我想介绍一些新的组件,还需要引入一个新的系统还是修改一个新的系统? 我经常阅读的另一件事是,实体的“types”是由它所具有的组件推断出来的。 如果我的实体只是一个ID,我怎么知道我的机器人实体需要被移动或渲染,从而被一些系统修改? 对不起,很长的post(或者至less从我的手机屏幕似乎是这样)!