修改场景实体查询为unordered_set存储,提升查询效率, 修改Physics的SyncScene也为unordered_set
This commit is contained in:
@@ -97,6 +97,10 @@ namespace Engine::ECS {
|
|||||||
// 按稳定 UUID 查实体(序列化/跨引用场景);找不到返回 entt::null
|
// 按稳定 UUID 查实体(序列化/跨引用场景);找不到返回 entt::null
|
||||||
Entity FindEntityByUUID(UUID uuid);
|
Entity FindEntityByUUID(UUID uuid);
|
||||||
|
|
||||||
|
// 全量重建 UUID → Entity 索引(序列化加载完调一次;运行期勿调,
|
||||||
|
// CreateEntity / FlushDestroyQueue 已增量维护)
|
||||||
|
void RebuildUuidIndex();
|
||||||
|
|
||||||
Registry& GetRegistry() { return m_Registry; }
|
Registry& GetRegistry() { return m_Registry; }
|
||||||
const Registry& GetRegistry() const { return m_Registry; } // 序列化等只读遍历
|
const Registry& GetRegistry() const { return m_Registry; } // 序列化等只读遍历
|
||||||
|
|
||||||
@@ -137,6 +141,12 @@ namespace Engine::ECS {
|
|||||||
Registry m_Registry;
|
Registry m_Registry;
|
||||||
std::vector<Entity> m_PendingDestroy;
|
std::vector<Entity> m_PendingDestroy;
|
||||||
Settings m_Settings;
|
Settings m_Settings;
|
||||||
|
|
||||||
|
// UUID → Entity 索引(O(1) FindEntityByUUID;SyncConstraints 每帧调用)
|
||||||
|
// CreateEntity / FlushDestroyQueue 增量维护;序列化加载后由
|
||||||
|
// RebuildUuidIndex() 全量重建一次(SceneSerializer 直接改 IdComponent.uuid
|
||||||
|
// 绕过 CreateEntity,仅靠增量会不同步)
|
||||||
|
std::unordered_map<UUID, Entity> m_UUIDToEntity;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Engine::ECS
|
} // namespace Engine::ECS
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
#include <glm/gtc/quaternion.hpp>
|
#include <glm/gtc/quaternion.hpp>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Engine {
|
namespace Engine {
|
||||||
@@ -126,7 +127,7 @@ namespace Engine {
|
|||||||
ECS::TransformComponent& tr);
|
ECS::TransformComponent& tr);
|
||||||
// 约束对账:owner 孤儿清理 / body 重建传染失效 / 建缺失与变更重建
|
// 约束对账:owner 孤儿清理 / body 重建传染失效 / 建缺失与变更重建
|
||||||
// invalidated = 本帧 SyncScene 中被销毁或重建 body 的实体位模式
|
// invalidated = 本帧 SyncScene 中被销毁或重建 body 的实体位模式
|
||||||
void SyncConstraints(const std::vector<u32>& invalidated);
|
void SyncConstraints(const std::unordered_set<u32>& invalidated);
|
||||||
void CreateConstraint(u32 ownerBits, u32 targetBits,
|
void CreateConstraint(u32 ownerBits, u32 targetBits,
|
||||||
const ECS::JointComponent& jc);
|
const ECS::JointComponent& jc);
|
||||||
void RemoveConstraint(u32 ownerBits);
|
void RemoveConstraint(u32 ownerBits);
|
||||||
|
|||||||
@@ -17,21 +17,30 @@ namespace Engine::ECS {
|
|||||||
{
|
{
|
||||||
Entity e = m_Registry.create();
|
Entity e = m_Registry.create();
|
||||||
// 出生即有:UUID(稳定身份)+ Transform(空间存在性,Unity 语义)
|
// 出生即有: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<TransformComponent>(e);
|
||||||
m_Registry.emplace<NameComponent>(e, NameComponent{std::move(name)});
|
m_Registry.emplace<NameComponent>(e, NameComponent{std::move(name)});
|
||||||
|
m_UUIDToEntity.emplace(id.uuid, e);
|
||||||
return EntityHandle{this, e};
|
return EntityHandle{this, e};
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity Scene::FindEntityByUUID(UUID uuid)
|
Entity Scene::FindEntityByUUID(UUID uuid)
|
||||||
{
|
{
|
||||||
if (!uuid.Valid()) return entt::null;
|
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;
|
void Scene::RebuildUuidIndex() {
|
||||||
m_Registry.view<IdComponent>().each([&](Entity e, IdComponent& id) {
|
m_UUIDToEntity.clear();
|
||||||
if (found == entt::null && id.uuid == uuid) found = e;
|
m_Registry.view<IdComponent>().each(
|
||||||
});
|
[&](Entity e, const IdComponent& id) {
|
||||||
return found;
|
m_UUIDToEntity.emplace(id.uuid, e);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::DestroyEntity(Entity e)
|
void Scene::DestroyEntity(Entity e)
|
||||||
@@ -70,6 +79,12 @@ namespace Engine::ECS {
|
|||||||
std::remove(siblings.begin(), siblings.end(), e),
|
std::remove(siblings.begin(), siblings.end(), e),
|
||||||
siblings.end());
|
siblings.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 销毁前先从 UUID 索引摘掉(销毁后实体不可访问)
|
||||||
|
if (const auto* id = m_Registry.try_get<IdComponent>(e)) {
|
||||||
|
m_UUIDToEntity.erase(id->uuid);
|
||||||
|
}
|
||||||
|
|
||||||
m_Registry.destroy(e); // entt 自动回收槽位并递增版本号
|
m_Registry.destroy(e); // entt 自动回收槽位并递增版本号
|
||||||
}
|
}
|
||||||
m_PendingDestroy.clear();
|
m_PendingDestroy.clear();
|
||||||
@@ -81,6 +96,7 @@ namespace Engine::ECS {
|
|||||||
//(registry.clear() 后队列里的句柄全部失效,直接丢弃即可)
|
//(registry.clear() 后队列里的句柄全部失效,直接丢弃即可)
|
||||||
m_PendingDestroy.clear();
|
m_PendingDestroy.clear();
|
||||||
m_Registry.clear();
|
m_Registry.clear();
|
||||||
|
m_UUIDToEntity.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityHandle Scene::GetEntityHandle(Entity e)
|
EntityHandle Scene::GetEntityHandle(Entity e)
|
||||||
|
|||||||
@@ -343,7 +343,7 @@ namespace Engine {
|
|||||||
void PhysicsWorld::SyncScene() {
|
void PhysicsWorld::SyncScene() {
|
||||||
auto ® = m_Scene.GetRegistry();
|
auto ® = m_Scene.GetRegistry();
|
||||||
auto &bi = m_System->GetBodyInterface();
|
auto &bi = m_System->GetBodyInterface();
|
||||||
std::vector<u32> invalidated; // 本帧销毁/重建 body → 约束失效传染
|
std::unordered_set<u32> invalidated; // 本帧销毁/重建 body → 约束失效传染
|
||||||
|
|
||||||
// 1. 孤儿清理:实体销毁 / 组件被移除 → 移除 body
|
// 1. 孤儿清理:实体销毁 / 组件被移除 → 移除 body
|
||||||
for (auto it = m_Bodies.begin(); it != m_Bodies.end();) {
|
for (auto it = m_Bodies.begin(); it != m_Bodies.end();) {
|
||||||
@@ -353,7 +353,7 @@ namespace Engine {
|
|||||||
bi.RemoveBody(it->second.id);
|
bi.RemoveBody(it->second.id);
|
||||||
bi.DestroyBody(it->second.id);
|
bi.DestroyBody(it->second.id);
|
||||||
m_BodyToEntity.erase(it->second.id.GetIndexAndSequenceNumber());
|
m_BodyToEntity.erase(it->second.id.GetIndexAndSequenceNumber());
|
||||||
invalidated.push_back(it->first);
|
invalidated.insert(it->first);
|
||||||
it = m_Bodies.erase(it);
|
it = m_Bodies.erase(it);
|
||||||
} else {
|
} else {
|
||||||
++it;
|
++it;
|
||||||
@@ -373,7 +373,7 @@ namespace Engine {
|
|||||||
bi.DestroyBody(found->second.id);
|
bi.DestroyBody(found->second.id);
|
||||||
m_BodyToEntity.erase(found->second.id.GetIndexAndSequenceNumber());
|
m_BodyToEntity.erase(found->second.id.GetIndexAndSequenceNumber());
|
||||||
m_Bodies.erase(found);
|
m_Bodies.erase(found);
|
||||||
invalidated.push_back(bits);
|
invalidated.insert(bits);
|
||||||
}
|
}
|
||||||
rb.bodyValid = false;
|
rb.bodyValid = false;
|
||||||
continue;
|
continue;
|
||||||
@@ -385,7 +385,7 @@ namespace Engine {
|
|||||||
bi.DestroyBody(found->second.id);
|
bi.DestroyBody(found->second.id);
|
||||||
m_BodyToEntity.erase(found->second.id.GetIndexAndSequenceNumber());
|
m_BodyToEntity.erase(found->second.id.GetIndexAndSequenceNumber());
|
||||||
m_Bodies.erase(found);
|
m_Bodies.erase(found);
|
||||||
invalidated.push_back(bits);
|
invalidated.insert(bits);
|
||||||
}
|
}
|
||||||
CreateBody(bits, rb, tr);
|
CreateBody(bits, rb, tr);
|
||||||
continue;
|
continue;
|
||||||
@@ -407,7 +407,7 @@ namespace Engine {
|
|||||||
bi.DestroyBody(rec.id);
|
bi.DestroyBody(rec.id);
|
||||||
m_BodyToEntity.erase(found->second.id.GetIndexAndSequenceNumber());
|
m_BodyToEntity.erase(found->second.id.GetIndexAndSequenceNumber());
|
||||||
m_Bodies.erase(found);
|
m_Bodies.erase(found);
|
||||||
invalidated.push_back(bits);
|
invalidated.insert(bits);
|
||||||
rb.bodyValid = false;
|
rb.bodyValid = false;
|
||||||
CreateBody(bits, rb, tr);
|
CreateBody(bits, rb, tr);
|
||||||
continue;
|
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 ® = m_Scene.GetRegistry();
|
auto ® = m_Scene.GetRegistry();
|
||||||
const auto tainted = [&invalidated](u32 bits) {
|
const auto tainted = [&invalidated](const u32 bits) {
|
||||||
return std::find(invalidated.begin(), invalidated.end(), bits)
|
return invalidated.count(bits);
|
||||||
!= invalidated.end();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 1. owner 实体/组件没了(或被禁用),或任一端 body 本帧被销毁/重建 → 移除
|
// 1. owner 实体/组件没了(或被禁用),或任一端 body 本帧被销毁/重建 → 移除
|
||||||
@@ -901,6 +900,7 @@ namespace Engine {
|
|||||||
rb.bodyValid = true;
|
rb.bodyValid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PhysicsWorld::RemoveBody(const u32 entityBits) {
|
void PhysicsWorld::RemoveBody(const u32 entityBits) {
|
||||||
const auto found = m_Bodies.find(entityBits);
|
const auto found = m_Bodies.find(entityBits);
|
||||||
if (found == m_Bodies.end()) return;
|
if (found == m_Bodies.end()) return;
|
||||||
|
|||||||
@@ -767,6 +767,10 @@ namespace Engine::Serialization {
|
|||||||
// 显式补算,否则首帧 World = 单位阵
|
// 显式补算,否则首帧 World = 单位阵
|
||||||
scene.UpdateTransforms();
|
scene.UpdateTransforms();
|
||||||
|
|
||||||
|
// 序列化加载绕过了 CreateEntity 的 UUID 增量维护(565 行直接覆盖
|
||||||
|
// IdComponent.uuid),全量重建一次索引,否则 FindEntityByUUID 会全失效
|
||||||
|
scene.RebuildUuidIndex();
|
||||||
|
|
||||||
ENGINE_INFO("SceneSerializer: loaded {} entities from '{}'",
|
ENGINE_INFO("SceneSerializer: loaded {} entities from '{}'",
|
||||||
parsed.size(), sourceName);
|
parsed.size(), sourceName);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user