# UI-Editor GameObject 缺口分析 > **基于**:XCEngine渲染引擎架构设计.md > **目标**:识别 UI 编辑器 GameObject.h 相对于 Engine 架构设计文档的缺失功能 > **日期**:2026-03-20 --- ## 架构参考 XCEngine 组件系统参考 **Unity 传统架构 (GameObject-Component Pattern)**: - **GameObject**:场景中的实体(UI Editor 中称 `Entity`) - **Component**:挂载到 GameObject 的功能模块(变换、渲染器等) - **TransformComponent**:每个 GameObject 都有的变换组件,管理位置/旋转/缩放 - **Scene/SceneManager**:场景管理和场景切换 --- ## Engine 模块现状 | 模块 | 状态 | UI Editor 对齐情况 | |-----|------|------------------| | Core (Event, Types) | ✅ 已实现 | UI 编辑器已复用 `XCEngine::Core::Event` | | Debug (Logger, LogLevel, LogEntry) | ✅ 已实现 | UI 编辑器已复用 `XCEngine::Debug::LogLevel` | | **Math (Vector3, Quaternion, Matrix4x4, Transform, Color)** | ✅ **已实现** | **可直接复用 Engine Math 类型** | | Memory | ✅ 已实现 | | | Threading | ✅ 已实现 | | | Containers | ✅ 已实现 | | | RHI / D3D12 | ✅ 已实现 | UI 编辑器自行实现(与 Engine 技术栈一致) | | Resources | ✅ 已实现 | | | **Components (GameObject, Component, System)** | ❌ **缺失** | UI 编辑器自行实现,待 Engine 实现后迁移 | | **Scene (Scene, SceneManager, SceneLoader, SceneSerializer)** | ❌ **缺失** | UI 编辑器自行实现,待 Engine 实现后迁移 | --- ## 一、Component 基类缺口 | 架构设计接口 | 函数签名 | 状态 | 说明 | |------------|---------|------|------| | `transform()` | `TransformComponent& transform() const` | ❌ 缺失 | 返回所在实体的 TransformComponent 引用 | | `GetScene()` | `Scene* GetScene() const` | ❌ 缺失 | 返回所属 Scene 指针 | | `FixedUpdate()` | `virtual void FixedUpdate()` | ❌ 缺失 | 物理更新(每固定帧) | | `LateUpdate()` | `virtual void LateUpdate(float deltaTime)` | ❌ 缺失 | 晚于 Update 执行 | | `OnEnable()` | `virtual void OnEnable()` | ❌ 缺失 | 组件启用时调用 | | `OnDisable()` | `virtual void OnDisable()` | ❌ 缺失 | 组件禁用时调用 | | `friend class` | `friend class GameObject` | ⚠️ 差异 | UI Editor 是 `friend class Entity` | **补充说明**: - UI Editor 的 `Component` 需要增加 `TransformComponent*` 获取方法以支持 Inspector 面板的变换编辑 - Engine 的 `m_gameObject` 在 UI Editor 中对应 `m_entity` --- ## 二、TransformComponent 缺口 ### 2.1 World 空间方法 | 架构设计接口 | 函数签名 | 状态 | 说明 | |------------|---------|------|------| | `GetPosition()` | `XCEngine::Math::Vector3 GetPosition() const` | ❌ 缺失 | 获取世界坐标 | | `SetPosition()` | `void SetPosition(const XCEngine::Math::Vector3& position)` | ❌ 缺失 | 设置世界坐标 | | `GetRotation()` | `XCEngine::Math::Quaternion GetRotation() const` | ❌ 缺失 | 获取世界旋转 | | `SetRotation()` | `void SetRotation(const XCEngine::Math::Quaternion& rotation)` | ❌ 缺失 | 设置世界旋转 | | `GetScale()` | `XCEngine::Math::Vector3 GetScale() const` | ❌ 缺失 | 获取世界缩放 | | `SetScale()` | `void SetScale(const XCEngine::Math::Vector3& scale)` | ❌ 缺失 | 设置世界缩放 | ### 2.2 方向向量 | 架构设计接口 | 函数签名 | 状态 | 说明 | |------------|---------|------|------| | `GetForward()` | `XCEngine::Math::Vector3 GetForward() const` | ❌ 缺失 | 获取前向向量 | | `GetRight()` | `XCEngine::Math::Vector3 GetRight() const` | ❌ 缺失 | 获取右向量 | | `GetUp()` | `XCEngine::Math::Vector3 GetUp() const` | ❌ 缺失 | 获取上向量 | ### 2.3 矩阵变换 | 架构设计接口 | 函数签名 | 状态 | 说明 | |------------|---------|------|------| | `GetLocalToWorldMatrix()` | `const XCEngine::Math::Matrix4x4& GetLocalToWorldMatrix() const` | ❌ 缺失 | 本地到世界矩阵(含缓存) | | `GetWorldToLocalMatrix()` | `XCEngine::Math::Matrix4x4 GetWorldToLocalMatrix() const` | ❌ 缺失 | 世界到本地矩阵 | ### 2.4 父子层级 | 架构设计接口 | 函数签名 | 状态 | 说明 | |------------|---------|------|------| | `GetParent()` | `TransformComponent* GetParent() const` | ❌ 缺失 | 获取父变换 | | `SetParent()` | `void SetParent(TransformComponent* parent, bool worldPositionStays = true)` | ❌ 缺失 | 设置父变换 | | `GetChild()` | `TransformComponent* GetChild(int index) const` | ❌ 缺失 | 按索引获取子变换 | | `Find()` | `TransformComponent* Find(const String& name) const` | ❌ 缺失 | 按名称查找子变换 | | `DetachChildren()` | `void DetachChildren()` | ❌ 缺失 | 断开所有子节点 | | `SetAsFirstSibling()` | `void SetAsFirstSibling()` | ❌ 缺失 | 设为第一个同级 | | `SetAsLastSibling()` | `void SetAsLastSibling()` | ❌ 缺失 | 设为最后一个同级 | | `GetSiblingIndex()` | `int GetSiblingIndex() const` | ❌ 缺失 | 获取同级索引 | | `SetSiblingIndex()` | `void SetSiblingIndex(int index)` | ❌ 缺失 | 设置同级索引 | ### 2.5 变换操作 | 架构设计接口 | 函数签名 | 状态 | 说明 | |------------|---------|------|------| | `LookAt(target)` | `void LookAt(const XCEngine::Math::Vector3& target)` | ❌ 缺失 | 朝向目标点 | | `LookAt(target, up)` | `void LookAt(const XCEngine::Math::Vector3& target, const XCEngine::Math::Vector3& up)` | ❌ 缺失 | 朝向目标点(指定上向量) | | `Rotate(eulers)` | `void Rotate(const XCEngine::Math::Vector3& eulers)` | ❌ 缺失 | 欧拉角旋转 | | `Rotate(axis, angle)` | `void Rotate(const XCEngine::Math::Vector3& axis, float angle)` | ❌ 缺失 | 轴角旋转 | | `Translate(translation)` | `void Translate(const XCEngine::Math::Vector3& translation)` | ❌ 缺失 | 平移(世界空间) | | `Translate(translation, relativeTo)` | `void Translate(const XCEngine::Math::Vector3& translation, Space relativeTo)` | ❌ 缺失 | 平移(指定空间) | ### 2.6 点/方向变换 | 架构设计接口 | 函数签名 | 状态 | 说明 | |------------|---------|------|------| | `TransformPoint()` | `XCEngine::Math::Vector3 TransformPoint(const XCEngine::Math::Vector3& point) const` | ❌ 缺失 | 变换点(含平移旋转) | | `InverseTransformPoint()` | `XCEngine::Math::Vector3 InverseTransformPoint(const XCEngine::Math::Vector3& point) const` | ❌ 缺失 | 逆变换点 | | `TransformDirection()` | `XCEngine::Math::Vector3 TransformDirection(const XCEngine::Math::Vector3& direction) const` | ❌ 缺失 | 变换方向(仅旋转) | | `InverseTransformDirection()` | `XCEngine::Math::Vector3 InverseTransformDirection(const XCEngine::Math::Vector3& direction) const` | ❌ 缺失 | 逆变换方向 | ### 2.7 脏标记与缓存 | 架构设计接口 | 函数签名 | 状态 | 说明 | |------------|---------|------|------| | `SetDirty()` | `void SetDirty()` | ⚠️ 局部 | UI Editor 只有简单 flag,缺少完整缓存机制 | | 缓存成员 | `mutable XCEngine::Math::Matrix4x4 m_localToWorldMatrix` 等 | ❌ 缺失 | 矩阵缓存 | | 更新方法 | `void UpdateWorldTransform() const` | ❌ 缺失 | 缓存失效时重新计算 | **当前 UI Editor 实现**: ```cpp class TransformComponent : public Component { public: float position[3] = {0.0f, 0.0f, 0.0f}; // 仅有本地坐标 float rotation[3] = {0.0f, 0.0f, 0.0f}; // 欧拉角 float scale[3] = {1.0f, 1.0f, 1.0f}; // 仅有本地缩放 // 缺少世界空间方法、矩阵缓存、父子指针等 }; ``` **架构设计要求**(应使用 Engine Math 类型): ```cpp class TransformComponent : public Component { public: // 使用 Engine Math 类型 XCEngine::Math::Vector3 GetLocalPosition() const { return m_localPosition; } void SetLocalPosition(const XCEngine::Math::Vector3& pos) { m_localPosition = pos; SetDirty(); } XCEngine::Math::Quaternion GetLocalRotation() const { return m_localRotation; } void SetLocalRotation(const XCEngine::Math::Quaternion& rot) { m_localRotation = rot; SetDirty(); } XCEngine::Math::Vector3 GetLocalScale() const { return m_localScale; } void SetLocalScale(const XCEngine::Math::Vector3& sc) { m_localScale = sc; SetDirty(); } private: XCEngine::Math::Vector3 m_localPosition = XCEngine::Math::Vector3::Zero(); XCEngine::Math::Quaternion m_localRotation = XCEngine::Math::Quaternion::Identity(); XCEngine::Math::Vector3 m_localScale = XCEngine::Math::Vector3::One(); TransformComponent* m_parent = nullptr; std::vector m_children; mutable XCEngine::Math::Matrix4x4 m_localToWorldMatrix; mutable XCEngine::Math::Matrix4x4 m_worldToLocalMatrix; mutable XCEngine::Math::Vector3 m_worldPosition; mutable XCEngine::Math::Quaternion m_worldRotation; mutable XCEngine::Math::Vector3 m_worldScale; mutable bool m_dirty = true; void UpdateWorldTransform() const; }; ``` --- ## 三、GameObject缺口 ### 3.1 基础方法 | 架构设计接口 | 函数签名 | 状态 | 说明 | |------------|---------|------|------| | `GetTransform()` | `TransformComponent& GetTransform()` | ❌ 缺失 | 获取变换组件引用 | | `GetScene()` | `Scene* GetScene() const` | ❌ 缺失 | 获取所属场景 | ### 3.2 组件查找 | 架构设计接口 | 函数签名 | 状态 | 说明 | |------------|---------|------|------| | `GetComponentInChildren()` | `T* GetComponentInChildren() const` | ❌ 缺失 | 在子实体中查找组件 | | `GetComponentsInChildren()` | `std::vector GetComponentsInChildren() const` | ❌ 缺失 | 获取所有子实体中的组件 | | `GetComponentInParent()` | `T* GetComponentInParent() const` | ❌ 缺失 | 在父实体中查找组件 | ### 3.3 父子层级 | 架构设计接口 | 函数签名 | 状态 | 说明 | |------------|---------|------|------| | `SetParent(parent)` | `void SetParent(Entity* parent)` | ❌ 缺失 | 2参数版本(含 worldPositionStays) | | `GetChildren()` | `const std::vector& GetChildren() const` | ❌ 缺失 | 获取子实体列表 | | `GetChild()` | `Entity* GetChild(int index) const` | ❌ 缺失 | 按索引获取子实体 | ### 3.4 激活状态 | 架构设计接口 | 函数签名 | 状态 | 说明 | |------------|---------|------|------| | `active` 成员 | `bool active = true` | ❌ 缺失 | 实体激活状态 | | `SetActive()` | `void SetActive(bool active)` | ❌ 缺失 | 设置激活状态 | | `IsActive()` | `bool IsActive() const` | ❌ 缺失 | 检查激活状态 | | `IsActiveInHierarchy()` | `bool IsActiveInHierarchy() const` | ❌ 缺失 | 检查层级中的激活状态 | ### 3.5 静态查找 | 架构设计接口 | 函数签名 | 状态 | 说明 | |------------|---------|------|------| | `Find()` | `static Entity* Find(const String& name)` | ❌ 缺失 | 按名称查找实体 | | `FindObjectsOfType()` | `static std::vector FindObjectsOfType()` | ❌ 缺失 | 查找所有实体 | | `FindGameObjectsWithTag()` | `static std::vector FindGameObjectsWithTag(const String& tag)` | ❌ 缺失 | 按标签查找 | ### 3.6 销毁 | 架构设计接口 | 函数签名 | 状态 | 说明 | |------------|---------|------|------| | `Destroy()` | `void Destroy()` | ❌ 缺失 | 实例方法销毁(通过 Scene) | --- ## 四、Scene / SceneManager 缺口 ### 4.1 Scene 类 | 架构设计接口 | 函数签名 | 状态 | 说明 | |------------|---------|------|------| | `GetName()` | `const String& GetName() const` | ❌ 缺失 | 获取场景名称 | | `SetName()` | `void SetName(const String& name)` | ❌ 缺失 | 设置场景名称 | | `CreateGameObject(name, parent)` | `Entity* CreateGameObject(const String& name, Entity* parent)` | ❌ 缺失 | 带父实体创建 | | `GetRootGameObjects()` | `std::vector GetRootGameObjects() const` | ❌ 缺失 | 获取根实体列表 | | `Find()` | `Entity* Find(const String& name) const` | ❌ 缺失 | 查找实体 | | `FindGameObjectWithTag()` | `Entity* FindGameObjectWithTag(const String& tag) const` | ❌ 缺失 | 按标签查找 | | `FindObjectsOfType()` | `std::vector FindObjectsOfType() const` | ❌ 缺失 | 模板查找 | | `FindObjectOfType()` | `T* FindObjectOfType() const` | ❌ 缺失 | 查找单个 | | `IsActive()` | `bool IsActive() const` | ❌ 缺失 | 场景激活状态 | | `SetActive()` | `void SetActive(bool active)` | ❌ 缺失 | 设置激活状态 | | `Load()` | `void Load(const String& filePath)` | ❌ 缺失 | 加载场景 | | `Save()` | `void Save(const String& filePath)` | ❌ 缺失 | 保存场景 | | `Update()` | `void Update(float deltaTime)` | ❌ 缺失 | 场景更新 | | `FixedUpdate()` | `void FixedUpdate(float fixedDeltaTime)` | ❌ 缺失 | 物理更新 | | `LateUpdate()` | `void LateUpdate(float deltaTime)` | ❌ 缺失 | 晚更新 | **当前 UI Editor 缺失 Scene 概念**,所有实体都在 SceneManager 全局管理。 ### 4.2 SceneManager 类 | 架构设计接口 | 函数签名 | 状态 | 说明 | |------------|---------|------|------| | `CreateScene()` | `Scene* CreateScene(const String& name)` | ❌ 缺失 | 创建场景 | | `LoadScene()` | `void LoadScene(const String& filePath)` | ❌ 缺失 | 同步加载 | | `LoadSceneAsync()` | `void LoadSceneAsync(const String& filePath, std::function callback)` | ❌ 缺失 | 异步加载 | | `UnloadScene(scene)` | `void UnloadScene(Scene* scene)` | ❌ 缺失 | 卸载场景 | | `UnloadScene(name)` | `void UnloadScene(const String& sceneName)` | ❌ 缺失 | 按名称卸载 | | `SetActiveScene(scene)` | `void SetActiveScene(Scene* scene)` | ❌ 缺失 | 设置激活场景 | | `SetActiveScene(name)` | `void SetActiveScene(const String& sceneName)` | ❌ 缺失 | 按名称设置 | | `GetActiveScene()` | `Scene* GetActiveScene() const` | ❌ 缺失 | 获取激活场景 | | `GetScene(name)` | `Scene* GetScene(const String& name) const` | ❌ 缺失 | 按名称获取场景 | | `GetAllScenes()` | `std::vector GetAllScenes() const` | ❌ 缺失 | 获取所有场景 | | `OnSceneLoaded` | `Event` | ⚠️ 差异 | UI Editor 是 `OnSceneChanged` | | `OnSceneUnloaded` | `Event` | ❌ 缺失 | 场景卸载事件 | | `OnActiveSceneChanged` | `Event` | ❌ 缺失 | 激活场景变更事件 | ### 4.3 GameObjectBuilder 类 | 架构设计接口 | 函数签名 | 状态 | 说明 | |------------|---------|------|------| | 完整类 | `class GameObjectBuilder` | ❌ 缺失 | 实体创建辅助类 | --- ## 五、实现优先级 ### P0 - 核心缺失(必须实现) | 模块 | 原因 | 涉及文件 | |-----|------|---------| | TransformComponent 世界空间方法 | Editor 变换编辑基础 | GameObject.h | | Entity `GetTransform()` | Inspector 面板需要 | GameObject.h | | Component `transform()` | 组件访问变换 | GameObject.h | **依赖**:Engine Math 模块 ✅ 已实现,可直接使用 `XCEngine::Math::Vector3` / `Quaternion` / `Matrix4x4`。 ### P1 - 功能完整(应该实现) | 模块 | 原因 | 涉及文件 | |-----|------|---------| | TransformComponent 矩阵缓存 | 性能优化 | GameObject.h | | TransformComponent 父子指针 | 层级操作 | GameObject.h | | Entity 激活状态 | 运行时状态 | GameObject.h | | Entity 父子层级操作 | 层级编辑 | GameObject.h | | Scene 概念 | 多场景支持 | SceneManager.h | | SceneManager 多场景管理 | 场景隔离 | SceneManager.h | ### P2 - 高级功能(可选实现) | 模块 | 原因 | 涉及文件 | |-----|------|---------| | Scene 序列化/反序列化 | 持久化 | SceneManager.h | | TransformComponent 点/方向变换 | Gizmos 操作 | GameObject.h | | SceneManager 异步加载 | 体验优化 | SceneManager.h | | Entity 静态查找 | Editor 操作 | GameObject.h | --- ## 六、数据结构对齐表 ### 6.1 当前 UI Editor vs 架构设计 | 项目 | UI Editor 当前 | 架构设计 | 对齐建议 | |-----|--------------|---------|---------| | 实体内组件存储 | `vector>` | `vector>` | ✅ 已对齐 | | 变换类型 | `float[3]` 数组 | `XCEngine::Math::Vector3` / `Quaternion` | ⚠️ **应改用 Engine Math** | | 父子关系 | `EntityID` (uint64) | `Entity*` 指针 | ⚠️ UI 用 ID,Engine 用指针 | | 场景管理 | 全局单例 SceneManager | 多 Scene + SceneManager | ❌ 需要重构 | ### 6.2 命名差异 | UI Editor | Engine 架构设计 | 说明 | |-----------|---------------|------| | `Entity` | `GameObject` | UI Editor 使用 Entity 避免与 std 冲突 | | `EntityID` | `uint64_t` | UI Editor 自定义类型别名 | | `INVALID_ENTITY_ID` | N/A | UI Editor 自定义常量 | | `ComponentRegistry` | `ComponentTypeRegistry` | 功能相似,命名不同 | ### 6.3 类型复用情况 | Engine 类型 | UI Editor 现状 | 建议 | |-----------|--------------|------| | `XCEngine::Math::Vector3` | UI Editor 用 `float[3]` | **直接复用** | | `XCEngine::Math::Quaternion` | UI Editor 用 `float[3]` (欧拉角) | **直接复用**,但欧拉角存储可保留 | | `XCEngine::Math::Matrix4x4` | 无 | **直接复用** | | `XCEngine::Core::Event` | ✅ 已复用 | 保持 | | `XCEngine::Debug::LogLevel` | ✅ 已复用 | 保持 | --- ## 七、依赖关系分析 ``` 实现优先级 - 依赖链: P0: TransformComponent 世界空间 │ ├── 需要: XCEngine::Math::Vector3 ✅ 已实现 ├── 需要: XCEngine::Math::Quaternion ✅ 已实现 ├── 需要: XCEngine::Math::Matrix4x4 ✅ 已实现 └── 影响: Entity::GetTransform() P0: Component::transform() │ └── 依赖: Entity::GetTransform() P1: TransformComponent 父子指针 │ ├── 需要: TransformComponent* parent ├── 需要: vector children └── 影响: Entity 父子操作 P1: Entity 激活状态 │ ├── 需要: active 成员 └── 影响: IsActiveInHierarchy() P1: Scene 多场景 │ ├── 需要: Scene 类 ├── 需要: Scene::CreateGameObject() └── 影响: SceneManager 重构 ``` --- ## 八、与 Unity 架构的对照 ### Unity 传统架构 (GameObject-Component) ``` Scene └── GameObject ("MyEntity") ├── Transform ├── MeshRenderer └── (其他组件...) GameObject.GetComponent() → Entity.GetComponent() GameObject.transform → Entity.GetTransform() GameObject.SetActive(bool) → 缺失 GameObject.Find("name") → 缺失 Scene.GetRootGameObjects() → 缺失 SceneManager.GetActiveScene() → 缺失 ``` ### UI Editor 当前实现 ``` SceneManager (全局单例) └── m_entities (unordered_map) └── Entity ("MyEntity") ├── id, name, parent, children ├── components (vector>) └── selected Entity.AddComponent() → ✅ 已实现 Entity.GetComponent() → ✅ 已实现 Entity.GetTransform() → ❌ 缺失 TransformComponent 世界空间方法 → ❌ 缺失 ``` --- ## 九、附录:当前 GameObject.h 完整内容 ```cpp // ui_editor/src/Core/GameObject.h 当前实现 #pragma once #include #include #include #include #include #include #include namespace UI { using EntityID = uint64_t; constexpr EntityID INVALID_ENTITY_ID = 0; class Component { public: virtual ~Component() = default; virtual std::string GetName() const = 0; virtual void Awake() {} virtual void Start() {} virtual void Update(float deltaTime) {} virtual void OnDestroy() {} class Entity* GetEntity() const { return m_entity; } bool IsEnabled() const { return m_enabled; } void SetEnabled(bool enabled) { m_enabled = enabled; } protected: class Entity* m_entity = nullptr; bool m_enabled = true; friend class Entity; }; class TransformComponent : public Component { public: float position[3] = {0.0f, 0.0f, 0.0f}; float rotation[3] = {0.0f, 0.0f, 0.0f}; float scale[3] = {1.0f, 1.0f, 1.0f}; std::string GetName() const override { return "Transform"; } }; class MeshRendererComponent : public Component { public: std::string materialName = "Default-Material"; std::string meshName = ""; std::string GetName() const override { return "Mesh Renderer"; } }; class Entity { public: EntityID id = INVALID_ENTITY_ID; std::string name; EntityID parent = INVALID_ENTITY_ID; std::vector children; std::vector> components; bool selected = false; template T* AddComponent(Args&&... args) { auto comp = std::make_unique(std::forward(args)...); comp->m_entity = this; T* ptr = comp.get(); components.push_back(std::move(comp)); return ptr; } template T* GetComponent() { for (auto& comp : components) { if (auto casted = dynamic_cast(comp.get())) { return casted; } } return nullptr; } template std::vector GetComponents() { std::vector result; for (auto& comp : components) { if (auto casted = dynamic_cast(comp.get())) { result.push_back(casted); } } return result; } }; using ComponentInspectorFn = std::function; struct ComponentInspectorInfo { std::string name; ComponentInspectorFn renderFn; }; class ComponentRegistry { public: static ComponentRegistry& Get() { static ComponentRegistry instance; return instance; } template void RegisterComponent(const std::string& name, ComponentInspectorFn inspectorFn) { m_inspectors[name] = {name, inspectorFn}; m_factories[name] = []() -> std::unique_ptr { return std::make_unique(); }; } ComponentInspectorInfo* GetInspector(const std::string& name) { auto it = m_inspectors.find(name); if (it != m_inspectors.end()) { return &it->second; } return nullptr; } private: ComponentRegistry() = default; std::unordered_map m_inspectors; std::unordered_map()>> m_factories; }; } // namespace UI ``` --- **文档结束**