我会尽量保持简短
上下文
我的基本 C++(SDL 和 OpenGL)2D 游戏引擎有一个 ECS。我有一个名为TextSystem的系统,它需要 3 个组件。变换组件、渲染组件和文本组件。
这是为系统设置的签名的代码片段。
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需要的所有组件,即转换和渲染组件。
因此,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中注册的实体重新分配渲染组件中的纹理变量时,应用的最新纹理(通过 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 小时......),谷歌搜索没有产生预期的结果。
如果需要任何东西(更多代码片段和/或上下文),请告诉我!我不确定这个问题是否适合 Stack Overflow 或 Game Development。