实体组件系统ECS:与该组件在所有实体之间共享的实体专有组件数据

问题描述

我会尽量保持简短

上下文

我的基本C ++(SDL和OpenGL)2D游戏引擎具有ECS。我有一个名为 TextSystem 的系统,该系统需要3个组件。 TransformComponent RenderComponent TextComponent

这是为系统设置的签名的代码段。

ECSHandler::Instance()->Init();

//Register components.
ECSHandler::Instance()->RegisterComponent<TransformComponent>();
ECSHandler::Instance()->RegisterComponent<RenderComponent>();
ECSHandler::Instance()->RegisterComponent<TextComponent>();

//movement signature here

renderSignature.set(ECSHandler::Instance()->GetComponentType<TransformComponent>());
renderSignature.set(ECSHandler::Instance()->GetComponentType<RenderComponent>());

textSignature.set(ECSHandler::Instance()->GetComponentType<TransformComponent>());
textSignature.set(ECSHandler::Instance()->GetComponentType<RenderComponent>());
textSignature.set(ECSHandler::Instance()->GetComponentType<TextComponent>());

//Register systems.
//mpMovementSystem = ECSHandler::Instance()->RegisterSystem<MovementSystem>();
mpRenderSystem = ECSHandler::Instance()->RegisterSystem<RenderSystem>();
mpTextSystem = ECSHandler::Instance()->RegisterSystem<TextSystem>();
//ECSHandler::Instance()->SetSystemSignature<MovementSystem>(signature);
ECSHandler::Instance()->SetSystemSignature<RenderSystem>(renderSignature);
ECSHandler::Instance()->SetSystemSignature<TextSystem>(textSignature);

//mpSystems.insert({ typeid(MovementSystem).name(),mpMovementSystem });
mpSystems.insert({ typeid(RenderSystem).name(),mpRenderSystem });
mpSystems.insert({ typeid(TextSystem).name(),mpTextSystem });

所有 TextSystem 所做的只是将 RenderComponent 中的“ texture”变量设置为由文本/字体制成的纹理。这是使用称为LoadTextureFromFont的函数完成的。

一个处理渲染的系统 RenderingSystem ,如果该实体已经像 RenderingSystem 一样注册 TextSystem ,则会自动添加该实体。 TextSystem 需要的所有组件,即 transform render 组件。

因此, TextSystem 更改实体的纹理以根据文本输入( TextComponent 中的“ output”变量)和 RenderSystem 渲染该实体。

    void TextSystem::Update()
    {
        for (auto const& entity : mEntities)
        {
            auto& render = ECSHandler::Instance()->GetComponent<RenderComponent>(entity);
            auto& text = ECSHandler::Instance()->GetComponent<TextComponent>(entity);

            render.texture = ResourceManager::LoadTextureFromFont(text.output,true,text.font);
        }
    }
    void RenderSystem::Draw()
    {
        for (auto const& entity : mEntities)
        {
        auto& transform = ECSHandler::Instance()->GetComponent<TransformComponent>(entity);
        auto& render = ECSHandler::Instance()->GetComponent<RenderComponent>(entity);

        ...

        glBindVertexArray(mQuadVAO);
        glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_INT,NULL);
        glBindVertexArray(0);
    }
}
RenderingSystem 的绘制之前调用

TextSystem 的更新。

问题

render 组件中为在 TextSystem 注册的实体重新分配纹理变量时,所应用的最新纹理(通过LoadTextureFromFont)将应用于所有实体具有 TextComponent 文件。本质上,对于具有该组件的所有实体,最后一个 TextComponent 变为 TextComponent 。纹理的大小是根据原始文本的大小来确定的,因此较长但已被最新文本替换的文本将看起来不成比例。

ResourceManager::AddText("testText","Message",glm::vec2(200.f,200.f),ResourceManager::GetFont("CircularMedium"));
ResourceManager::AddText("testText2","This is a message.",glm::vec2(300.f,ResourceManager::GetFont("CircularMedium"));

enter image description here

其他任何组件都不会发生这种情况,严格来说,该组件(仅包含字符串和字体对象)似乎不是实体专有的。

我已经尽力解决了这个问题(10-12小时...),但Google搜索没有产生预期的结果。

如果需要任何内容​​(更多代码段和/或上下文),请告诉我!我不确定这个问题是否适合Stack Overflow或Game Development。

解决方法

从GetTextureFromFont返回的“ Texture”变量是全局变量。