【发布时间】:2021-05-05 21:57:55
【问题描述】:
我在搞乱a small ECS implementation found here。我慢慢复制代码来理解它,它工作正常。但是,在尝试添加 ECS 的“系统”部分之前,我尝试将功能分离到不同的类中,并使用“协调器”类抽象所有内容,而不是一个大的命名空间。
所以我有这样的东西(对不起,如果我的代码提前不好,还在学习C++):
// ECSCoordinator.h
#ifndef I3D_ECS_COORDINATOR_H
#define I3D_ECS_COORDINATOR_H
#include <memory>
#include "Entity.h"
#include "EntityManager.h"
#include "ComponentContainer.h"
class ECSCoordinator {
public:
ECSCoordinator();
Entity create_entity();
void delete_entity();
template<typename Component>
void add_component_to(Entity e, Component c);
private:
template<class Component>
static ComponentContainer<Component> registry;
std::unique_ptr<EntityManager> entity_manager;
};
template<typename Component>
void ECSCoordinator::add_component_to(Entity e, Component c) {
registry<Component>.insert(e, c);
}
// ECSCoordinator.cpp
#include "ECSCoordinator.h"
#include "ECS/Entity.h"
#include "ECS/EntityManager.h"
ECSCoordinator::ECSCoordinator()
: entity_manager(std::make_unique<EntityManager>()) {}
Entity ECSCoordinator::create_entity() {
return entity_manager->create_entity();
}
#endif // I3D_ECS_COORDINATOR_H
我必须决定的一件事是在哪里声明registry。在最初的实现中,它是在命名空间的范围内声明的,但是一旦我将东西移动到类中,我不想让一个全局变量坐在那里。因此,我将变量模板设置为协调器的静态类成员。我相信这些是等价的?然后ComponentContainer 的前向声明不再起作用,因为我在标题中定义add_component_to,所以我不得不改为#include "ComponentContainer.h",这意味着我必须将ComponentContainer 中的静态定义移动到他们自己的.cpp 文件中(如果这很重要)。
除此之外,使 Entity.h 成为 POD(仅包含一个无符号整数)和 EntityManager.h 负责创建具有递增 ID 的实体,我没有太大变化。
所以当我想使用系统时,我想这样做:
std::unique_ptr<ECSCoordinator> coordinator = std::make_unique<ECSCoordinator>();
Entity fish = coordinator->create_entity();
coordinator->add_component_to(fish, Animal("Fish"));
但是,当我尝试将 (key, value) 添加到无序映射(tiny_ecs.hpp 的第 100 行)时,这些更改会导致读取访问冲突:
map_entity_component_index[e.id] = component_index;
我可以肯定地确认e.id = 0 和component_index = 1 是第一次添加。我可以在这个错误之前在无序映射上运行一个方法,比如size()。但是,尝试向地图添加内容会导致崩溃。
我不确定如何解释我在调试器中看到的错误:
感谢任何提供帮助的人。
【问题讨论】:
-
什么是
map_entity_component_index?它是在哪里定义的? -
tiny_ecs.hpp第 100 行的评论看起来有点麻烦:map_entity_component_index[e.id] = component_index; // Note, not using insert or emplace to allow inserting multiple components for the same entity (at your own risk)- 我想知道“风险自负”是什么意思。 -
@1201ProgramAlarm map_entity_component_index 是 ComponentContainer 继承自的类中的受保护成员。
-
它没有在任何地方定义,但是,它只是被声明了。在原始实现中。通过调用
registry<ComponentClass>.insert(entity, component),即registry<WaterAnimal>.insert(fish, WaterAnimal()),将某个实体的组件添加到注册表。我相信这隐含地实例化了registry<WaterAnimal>,其中一个指针保存在第 76 和 77 行(因为注册表的类型为ComponentContainer<Component>,而static std::vector<ContainerInterface*>(参见 tiny_ecs.cpp)是一个带有ComponentContainer类指针的单例继承自)。
标签: c++ templates runtime-error