【问题标题】:Entity Component System (ECS): Entity-Exclusive Component Data Being Shared Among All Entities With That Component实体组件系统 (ECS):实体专有组件数据在具有该组件的所有实体之间共享
【发布时间】:2021-02-20 01:29:37
【问题描述】:

我会尽量保持简短

背景

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

这是为系统设置的签名的代码 sn-p。

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 中的“纹理”变量设置为由文本/字体构成的纹理。这是使用名为 LoadTextureFromFont 的函数完成的。

另一个处理渲染的系统,RenderingSystem,如果它已经像 RenderingSystem 一样注册到 TextSystem,它会自动添加实体TextSystem 需要的所有组件,transformrender 组件。

因此,TextSystem 会根据文本输入(TextComponent 中的“输出”变量)和 更改实体的纹理以更新它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);
    }
}

TextSystem 的 Update 在 RenderingSystem 的 Draw 之前调用。

问题

当为在 TextSystem 中注册的实体重新分配 render 组件中的纹理变量时,最新应用的纹理(通过 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, 200.f), ResourceManager::GetFont("CircularMedium"));

这不会发生在任何其他组件上,严格来说,这个组件(它只包含一个字符串和字体对象)似乎不是实体专有的。

我已尽我所能解决此问题(10 到 12 小时...),但谷歌搜索没有产生预期的结果。

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

【问题讨论】:

    标签: c++ opengl 2d sdl entity-component-system


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 2019-05-03
      • 2016-11-05
      • 2020-03-06
      • 2018-01-05
      • 2018-08-13
      • 2019-08-06
      • 2016-01-23
      • 2017-01-04
      • 2014-07-06
      相关资源
      最近更新 更多