0

我已经开始关注 YouTube 上的 ECS 教程,而且我从未见过有人将新变量分配到 a vectorofuint8之前。

template<typename Component>
uint32 ECSComponentCreate(Array<uint8>& memory, EntityHandle entity, BaseECSComponent* comp)
{
    uint32 index = memory.size();
    memory.resize(index+Component::SIZE);
    Component* component = new(&memory[index])Component(*(Component*)comp);
    component->entity = entity;
    return index;
}

(有问题的完整代码可以在这里找到;Array这里是#define Array std::vector

它与使用指针向量有何不同,为什么它更好?

4

2 回答 2

1

这基本上是一个“池分配器”。既然您知道它叫什么,您就可以了解它为什么这样做,但性能通常是动机。

所有分配都在一个向量中完成,最后整个向量可以立即释放(在销毁其中的对象之后,您可以在下面的释放函数中看到)。

于 2018-08-04T10:09:15.297 回答
0

使用 a vectorof bytes 对我来说有两个问题:

  1. 结盟。尽管您可以使用对齐的分配器来解决这个问题。如果您不知道提前存储了哪些类型以及它们在运行时之前的对齐要求,那么稍微浪费(但对于少数大型容器来说不是那么多)只是为动态分配使用最大对齐。
  2. 这是我书中更大的问题,这与向量在向其插入元素时如何重新分配其数组有关。如果您在其中存储非平凡的构造/可破坏类型,则可能会通过在内存中复制它们的字节而没有正确调用必要的移动/复制ctors和dtors而造成严重破坏。

如果你想让你的 ECS 在内存中连续存储全新的组件类型,那么我推荐的一种危险性更小的方法是抽象你的组件容器,如下所示:

struct Components
{
     virtual ~Components() {}
};

template <class T>
struct ComponentsT: public Components
{
     std::vector<T> components;
};

当您想向Foo系统注册新的组件类型时,您可以动态分配和实例化ComponentsT<Foo>,将其粘贴在多态容器(容器的容器)中,以及当您想将Foo组件添加到实体时(并因此实例化并将其添加到组件列表中),获取相关的抽象Components*基指针/引用,将其向下转换(可以使用dynamic_cast)到ComponentsT<Foo>*,然后将您的组件实例推回那里。现在您将所有内容Foos连续存储在内存中,而无需处理对齐和失效等。

于 2018-12-25T21:22:48.783 回答