修改场景实体查询为unordered_set存储,提升查询效率, 修改Physics的SyncScene也为unordered_set

This commit is contained in:
2026-10-04 19:12:53 +08:00
parent b78d9fb4c9
commit c1854453e5
5 changed files with 47 additions and 16 deletions
+22 -6
View File
@@ -17,21 +17,30 @@ namespace Engine::ECS {
{
Entity e = m_Registry.create();
// 出生即有:UUID(稳定身份)+ Transform(空间存在性,Unity 语义)
m_Registry.emplace<IdComponent>(e, IdComponent{UUID::New()});
const auto& id = m_Registry.emplace<IdComponent>(e, IdComponent{UUID::New()});
m_Registry.emplace<TransformComponent>(e);
m_Registry.emplace<NameComponent>(e, NameComponent{std::move(name)});
m_UUIDToEntity.emplace(id.uuid, e);
return EntityHandle{this, e};
}
Entity Scene::FindEntityByUUID(UUID uuid)
{
if (!uuid.Valid()) return entt::null;
const auto it = m_UUIDToEntity.find(uuid);
// 防御:实体可能已销毁(map 仍残留过时项),二次校验 valid
if (it == m_UUIDToEntity.end() || !m_Registry.valid(it->second)) {
return entt::null;
}
return it->second;
}
Entity found = entt::null;
m_Registry.view<IdComponent>().each([&](Entity e, IdComponent& id) {
if (found == entt::null && id.uuid == uuid) found = e;
});
return found;
void Scene::RebuildUuidIndex() {
m_UUIDToEntity.clear();
m_Registry.view<IdComponent>().each(
[&](Entity e, const IdComponent& id) {
m_UUIDToEntity.emplace(id.uuid, e);
});
}
void Scene::DestroyEntity(Entity e)
@@ -70,6 +79,12 @@ namespace Engine::ECS {
std::remove(siblings.begin(), siblings.end(), e),
siblings.end());
}
// 销毁前先从 UUID 索引摘掉(销毁后实体不可访问)
if (const auto* id = m_Registry.try_get<IdComponent>(e)) {
m_UUIDToEntity.erase(id->uuid);
}
m_Registry.destroy(e); // entt 自动回收槽位并递增版本号
}
m_PendingDestroy.clear();
@@ -81,6 +96,7 @@ namespace Engine::ECS {
//(registry.clear() 后队列里的句柄全部失效,直接丢弃即可)
m_PendingDestroy.clear();
m_Registry.clear();
m_UUIDToEntity.clear();
}
EntityHandle Scene::GetEntityHandle(Entity e)
+9 -9
View File
@@ -343,7 +343,7 @@ namespace Engine {
void PhysicsWorld::SyncScene() {
auto &reg = m_Scene.GetRegistry();
auto &bi = m_System->GetBodyInterface();
std::vector<u32> invalidated; // 本帧销毁/重建 body → 约束失效传染
std::unordered_set<u32> invalidated; // 本帧销毁/重建 body → 约束失效传染
// 1. 孤儿清理:实体销毁 / 组件被移除 → 移除 body
for (auto it = m_Bodies.begin(); it != m_Bodies.end();) {
@@ -353,7 +353,7 @@ namespace Engine {
bi.RemoveBody(it->second.id);
bi.DestroyBody(it->second.id);
m_BodyToEntity.erase(it->second.id.GetIndexAndSequenceNumber());
invalidated.push_back(it->first);
invalidated.insert(it->first);
it = m_Bodies.erase(it);
} else {
++it;
@@ -373,7 +373,7 @@ namespace Engine {
bi.DestroyBody(found->second.id);
m_BodyToEntity.erase(found->second.id.GetIndexAndSequenceNumber());
m_Bodies.erase(found);
invalidated.push_back(bits);
invalidated.insert(bits);
}
rb.bodyValid = false;
continue;
@@ -385,7 +385,7 @@ namespace Engine {
bi.DestroyBody(found->second.id);
m_BodyToEntity.erase(found->second.id.GetIndexAndSequenceNumber());
m_Bodies.erase(found);
invalidated.push_back(bits);
invalidated.insert(bits);
}
CreateBody(bits, rb, tr);
continue;
@@ -407,7 +407,7 @@ namespace Engine {
bi.DestroyBody(rec.id);
m_BodyToEntity.erase(found->second.id.GetIndexAndSequenceNumber());
m_Bodies.erase(found);
invalidated.push_back(bits);
invalidated.insert(bits);
rb.bodyValid = false;
CreateBody(bits, rb, tr);
continue;
@@ -456,11 +456,10 @@ namespace Engine {
// ---- 约束对账 ----
void PhysicsWorld::SyncConstraints(const std::vector<u32> &invalidated) {
void PhysicsWorld::SyncConstraints(const std::unordered_set<u32> &invalidated) {
auto &reg = m_Scene.GetRegistry();
const auto tainted = [&invalidated](u32 bits) {
return std::find(invalidated.begin(), invalidated.end(), bits)
!= invalidated.end();
const auto tainted = [&invalidated](const u32 bits) {
return invalidated.count(bits);
};
// 1. owner 实体/组件没了(或被禁用),或任一端 body 本帧被销毁/重建 → 移除
@@ -901,6 +900,7 @@ namespace Engine {
rb.bodyValid = true;
}
void PhysicsWorld::RemoveBody(const u32 entityBits) {
const auto found = m_Bodies.find(entityBits);
if (found == m_Bodies.end()) return;
@@ -767,6 +767,10 @@ namespace Engine::Serialization {
// 显式补算,否则首帧 World = 单位阵
scene.UpdateTransforms();
// 序列化加载绕过了 CreateEntity 的 UUID 增量维护(565 行直接覆盖
// IdComponent.uuid),全量重建一次索引,否则 FindEntityByUUID 会全失效
scene.RebuildUuidIndex();
ENGINE_INFO("SceneSerializer: loaded {} entities from '{}'",
parsed.size(), sourceName);
return true;