Система компонентов сущностей (ECS): данные компонента, не связанные с сущностями, совместно используются всеми сущностями с этим компонентом

Я постараюсь сохранить это кратко

КОНТЕКСТ

Мой базовый движок для 2D-игр на C ++ (SDL и OpenGL) имеет 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 на текстуру, созданную из текста / шрифта. Это делается с помощью функции LoadTextureFromFont.

Другая система, которая обрабатывает рендеринг, RenderingSystem, автоматически добавляет объект, если он уже зарегистрирован в TextSystem, поскольку RenderingSystem имеет все компоненты. необходимые для TextSystem компоненты transform и render.

Итак, 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 вызывается перед Draw для RenderingSystem.

ПРОБЛЕМА

При повторном назначении переменной текстуры в компоненте 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, 200.f), ResourceManager::GetFont("CircularMedium"));

введите описание изображения здесь

Этого не происходит ни с одним другим компонентом, строго этот компонент (который содержит только строку и объект шрифта), по-видимому, не является эксклюзивным для сущностей.

Я пробовал все, что мог, чтобы исправить это (10-12 часов ...), и поиск в Google не дал желаемых результатов.

Если что-нибудь вообще понадобится (дополнительные фрагменты кода и / или контекст), пожалуйста, дайте мне знать! Я не уверен, подходит ли этот вопрос для переполнения стека или разработки игр.


person Ramin Amiri    schedule 07.11.2020    source источник


Ответы (1)


Переменная текстуры, возвращаемая GetTextureFromFont, была глобальной переменной.

person Ramin Amiri    schedule 08.11.2020