问题标签 [entity-component-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.
c++ - 四嵌套 unordered_map 怪物的替代方案?
我一直在尝试寻找一种有效的方法来存储和检索许多对象。让我解释一下我想要实现的目标,然后列出我想出的选项(但我不满意)。
以下在技术上做了我需要它做的事情,但显然是一个禁忌:
最内部的地图根据其 ID 保存组件。它之前的每个类型都有一个映射(组件的子类)。后者是这样完成的,以便当我检索它们时,我可以完全安全地动态地将它们转换为它们的类型,因为知道 TYPE 哈希映射只包含它们的类型的指针,还允许使用 count 来快速检查某个 ID 是否存在某些东西. 后面的地图按层存储,第一个地图按场景存储。在任何时候,将举行大约 30-50 个场景,每个场景包含大约 6-10 个图层,每个图层包含大约 30-40 个类型,每个类型包含 1 到 500 个对象。
每个循环我们都会根据指针的类型迭代指针,一次一层。场景很少改变(每 2-3 分钟)。使用 Type 和 Id 的组合访问组件。代码会定期检查哪些其他组件类型存在于同一 Id 中。场景、层和类型可以通过它们的名称进行访问,名称存储为 32 位 CRC 散列。速度至关重要。ID 是由代码分配的数字,只是从 0 开始。ID 在每个场景中都是唯一的。
毫无疑问,有一些疯狂的(阅读:常见的)成语可以帮助我,而我从未听说过。有谁知道吗? 到目前为止,我提出的任何替代方案都不可接受,但无论如何我都会列出它们:
选项1:
组件保存它来自哪个类型、场景和图层,每当我们遍历所有条目时,我们都会忽略不来自当前场景或图层的条目。或者,按顺序存储它们,以便您只需在一定范围内进行迭代。向量包含组件,当我们需要访问某种类型的组件时,我们会通过向量进行搜索。不理想,因为它需要一个周期进行多次搜索。或者使用 unordered_map 代替向量。
选项 2:
与嵌套地图相同,但带有向量。映射将 Id 转换为向量内的索引。
选项 3:
(Type / Layer / Scene / Id) -> Component* 简单地用向量的索引存储所有组件。有一个 unordered_map,其中包含主存储向量中的索引向量。当我们检查两者之间的冲突时,ID 和字符串哈希都可以存在(不太可能)。对于场景、图层和类型,名称必须是唯一的。ID 返回该 ID 的组成部分的所有索引的向量,名称或类型返回包含该类型或场景的所有索引的向量。感觉 hackish,所有这些向量的迭代。
选项 4:
组件获取一个“Component* next”指针来遍历属于同一实体的组件。最后一个组件链接到第一个。组件再次获得类型和场景/图层成员。
c++ - 如何从接口获取派生类?
在尝试用 C++ 创建实体组件系统时,由于缺乏对语言的了解,我遇到了一些问题。
使用一个类Entity,它包含接口IComponent(它的作用更像是一个表示“我持有数据”的标志),我有一个方法Add,如果没有同一个类的另一个 IComponent 已经在它。
这是一个过于简化的示例代码:
我的预期结果是
但我不知道如何从 IComponents 列表中获取 Foo 和 Bar 的基类并检查它们是否重复。
我怎样才能得到它们?如果 Foo 在 IComponent 列表中,我如何将 IComponent 转换为 Foo?
c++ - Entity-Component-System 中的拆分组件需要过多的重构
我有一个使用实体组件系统 (ECS) 的现有 C++ 游戏库。
我的图书馆的用户想创建一些组件,例如Cat
:-
他可以修改hp
每一个cat
,例如:-
几天后,他想Cat
分手HP
:Flyable
-
因此,每次cat
访问hp
都会编译错误(例如,#1
在上面的代码中)。
为了解决这个问题,用户可以将他的代码重构为:-
它可以工作,但需要在用户代码中进行大量重构(调用 的各个地方cat->hp
)。
在 ECS 中拆分组件时如何编辑框架/引擎以解决可维护性问题?
我从未发现任何不受此问题影响的方法,例如:-
- https://github.com/skypjack/entt
(开源-搜索vel.dx = 0.;
线路) - https://medium.com/@savas/nomad-game-engine-part-2-ecs-9132829188e5
(博客-搜索int currentHealth;
行) - https://www.randygaul.net/2013/05/20/component-based-engine-design/
(博客-搜索comp->DoStuff( dt );
行) - (C#,Unity3D)http://www.sebaslab.com/learning-svelto-ecs-by-example-the-unity-survival-example/
(由https://codereview.stackexchange.com/questions/引用的博客48536/an-ecs-model-for-game-development ;
搜索playerGunComponent.timer += _time.deltaTime;
)
赏金原因
Yuri 的回答是一个很酷的技术,但它仍然需要一些重构。
我当前糟糕的解决方案(pimpl)
如果我想创建Cat
,我将创建 6 个组件:-
Hp_
,Hp_OO
Flyable_
,Flyable_OO
Cat_
,Cat_OO
这是一个代码示例:-
现在,调用是有效的:-
实施:-
- 如果用户添加
Cat_OO
到实体,我的游戏引擎会自动将其父类添加到实体,例如Hp_
、Hp_OO
、Flyable_
、Flyable_OO
和Cat_
。 pimpl 的正确指针/句柄也必须分配。
^ 两个动作都可以使用回调。
缺点是:-
- 需要创建很多组件。(浪费记忆)
- 如果有一个通用的基类,例如
BaseComponent
,我需要虚拟继承。(浪费大量内存)
优点是:-
- 如果用户查询
getAll<Hp_OO>()
,Hp_OO
of eachCat_OO
也将在返回的列表中。 - 无需重构。
unity3d - 如何实施“可见性系统”
我已经设法在不在屏幕上的实体上禁用动画。但是,我正在寻找一种更纯粹的基于数学的方法(而不是视口点技巧)。有人知道我怎样才能有效地“Jobify”这段代码吗?
data-structures - 如何处理 ECS 中的动态分层实体
这是一个类比:我有一个由细胞组成的有机体,这些细胞可以进一步由一系列附件组成。
我目前拥有的是一种子/父母之间的事件链来处理附加和分离组件(这可能会影响链上的任何东西),它根本不涉及 ecs,它们是实体中的函数。
现在我已经使用了事件组件(用于对象上的鼠标事件)。如果我希望系统是纯的,我会在附加组件等时创建附加组件吗?即便如此,我如何才能让所有必要的接收者进入使用该组件的系统?以这种方式而不是一系列功能来处理它是否值得?有没有更好的办法?
c# - 具有本机集合的 Unity 作业系统比具有 C# 集合的作业系统慢
我目前正在研究一个 CPU 非常繁重的模拟,并且已经转移到作业系统 + 突发编译,并且可以大大提高性能。也就是说,切换到工作系统创造了一个新的瓶颈。我想问是否有任何方法可以规避这种情况。
这是我的模拟的工作原理。它基本上在世界空间中移动一个 2d 矩形并捕获路径上的网格坐标。没有工作,最大的瓶颈是SampleLine
,有了工作系统,瓶颈是trajectory.Add
/.AddNative
和occupied.IndexOf
。
trajectory.Add
使用 a Dictionary<int2, float2>
,而 .AddNative 使用 aNativeHashMap<int2, float2>
来存储值。trajectory.Add
几乎是 AddNative 的两倍,即使我必须先将 NativeList 的所有值复制到一个无用的 List 中。通过使用 Array 作为缓冲区,我可能会使其更快。
这是使用的工作:
现在我的问题是,如何防止代价高昂的NativeList
vsList
转换?为什么将 a 添加NativeList
到 aNativeHashMap
比将 a 转换NativeList
为 aList
并将该列表添加到 a 慢Dictionary
?
另外,将工作分成更小的工作可能会更好,因为我可以调用SampleLine
甚至WorldToCell
并行调用?但是我不知道工作是否可以开始其他工作,或者我是否应该只做WorldToCell
一份工作(因为它被称为最多)并在普通 C# 中完成其余的工作?我对工作系统完全陌生,所以我不知道应该如何“工作”。我可以把它留在一个大工作中,我可以做很多小工作,WorldToCell
或者我可以把所有三个计算都做一个工作。
unity3d - Unity3D 即将推出的 ECS 与当前层次结构
介绍
我一直在关注 Unity3D 的 DOTS 开发,并且一直在做一些关于让 ECS 运行的教程。但是,我没有发现 Unity3D 正在弃用他们当前的 GameObject/Hierarchy 方法并用新的 Entity/ECS 方法取而代之这一点很明显。
理论
目前,它似乎是两者的混合体,因此通常属于对象池或可能导致内存碎片的任何东西(射弹、物品、重生单位等)都使用 Entity/ECS,其余的仍然使用 GameObject/Hierarchy .
这对我来说似乎不太理想,因为非最佳方法将阻止进入最佳方法等待的下一帧。如果只使用 ECS,你会得到更多的帧,这有点意思......
另一方面,必须让设计师和动画师使用 ECS 之类的东西会很昂贵(目前)并且技术含量更高。编辑器中的当前 ECS 窗口并不是很直观,它不是一个工具,而不仅仅是一个结果输出。
问题
所以我的问题是,Unity3D 是否计划保留混合方法,如果是,我们如何选择是使用实体还是游戏对象?或者如果他们只使用 ECS 方法,是否会更改当前的实体编辑器窗口以适应设计师/动画师?
java - Java - 铸造 Set 的缺点?
我正在用 Java 开发一个基本的基于实体组件系统的游戏引擎,以获得乐趣。
我需要一种快速的方法来获取Component
某种类型的所有 s。例子:
所以我有一个ComponentManager
应该处理这个的:
我的 IDE 不喜欢(Set<T>) active.get(compClass);
(以黄色突出显示)。然而,这是基于非常基本的测试,并且比单独铸造每个项目Set
并将它们添加到新的更快Set
,但是这样做的潜在缺点是什么?
java - 在 Java 中存储 ECS 的组件
我正在使用 ECS(实体组件系统)在 java 中创建一个网络游戏,这是我第一次使用 ECS。我不确定我应该如何存储组件。我确实想使用一个实体类,我将在其中存储该特定实体的组件,但是如何?我是否应该从基类扩展所有组件并将它们存储在数组列表中?我应该使用集合吗?我基本上只是问是否有人对如何做到这一点有任何建议?谢谢。
c++ - 在 C++ 中将系统与 ECS(实体组件系统)管理器分离
我目前正在制作一个实体-组件-系统程序作为学习 C++ 的一种方式(我知道这可能不是推荐的方式,但我很开心)。到目前为止进展顺利,但我希望对其进行更多改进。
当前,每个系统都添加到 ECS 管理器中,std::function
并附有它需要运行的组件的签名。我当前的策略是遍历每个系统和实体,如果组件签名匹配,则使用实体 ID 作为参数调用系统函数。
此函数通过以下方法附加到 Manager:
ComponentA
并且ComponentB
只是泛型类型。我什至可以让一个组件成为一个float
或者int
如果我需要的话。使用时getComponent<T>()
,这些被转换为适当的指针。
这一切都完美无缺,但最终发生的是我必须为每个系统包含管理器的头文件,我希望它们不要相互绑定(我想这将是关注点分离)。
最好每个过程最终看起来都类似于:
系统唯一需要知道的是它正在处理的特定实体的组件指针。
我目前std::unordered_map
根据其类型的位掩码将组件存储在一个中。当需要一个组件时,模板提供了我能够从中制作位掩码然后转换它的类型。我不确定是否可以存储要转换的组件的类型,所以我认为每个组件都必须作为 void 指针传递给函数。但是 C++ 不允许我在void*
不知道类型的情况下从 a 隐式转换为另一个指针。有没有办法可以存储每个组件的类型以便以后需要时进行转换?
我想我可能只void*
为系统所需的每个组件定义函数,但直观地说这似乎是个坏主意。它根本不是类型安全的,我无法通过查看函数声明来知道它需要什么参数。
如何将引用传递给可以采用任意数量的任何类型的指针的函数?有没有办法通过模板来做到这一点,或者我可以在不知道类型的情况下隐式转换一个 void 指针?我也对其他策略持开放态度。