docs: refactor Components API content
This commit is contained in:
@@ -2,33 +2,119 @@
|
||||
|
||||
**命名空间**: `XCEngine::Components`
|
||||
|
||||
**类型**: `class (singleton)`
|
||||
**类型**: `class`
|
||||
|
||||
**头文件**: `XCEngine/Components/ComponentFactoryRegistry.h`
|
||||
|
||||
**描述**: 定义 `XCEngine/Components` 子目录中的 `ComponentFactoryRegistry` public API。
|
||||
**描述**: 维护“组件类型名 -> 创建函数”的全局注册表,供场景反序列化按类型名恢复组件实例。
|
||||
|
||||
## 概述
|
||||
## 角色概述
|
||||
|
||||
`ComponentFactoryRegistry.h` 是 `XCEngine/Components` 子目录 下的 public header,当前页面作为平行目录中的 canonical 总览,用于汇总该头文件暴露的主要声明。
|
||||
`ComponentFactoryRegistry` 是 `Components` 模块和场景文本反序列化之间的桥梁。
|
||||
|
||||
## 声明概览
|
||||
当 [Scene::DeserializeFromString](../../Scene/Scene/DeserializeFromString.md) 读到类似下面的记录时:
|
||||
|
||||
| 声明 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `ComponentFactoryRegistry` | `class` | 头文件中的公开声明。 |
|
||||
```text
|
||||
component=Camera;projection=0;fov=60;...
|
||||
```
|
||||
|
||||
## 公共方法
|
||||
它需要先回答一个问题: `"Camera"` 应该创建成什么 C++ 类型?
|
||||
|
||||
| 方法 | 描述 |
|
||||
|------|------|
|
||||
| [Get](Get.md) | 获取相关状态或对象。 |
|
||||
| [RegisterFactory](RegisterFactory.md) | 注册对象、回调或映射。 |
|
||||
| [CreateComponent](CreateComponent.md) | 创建新对象或资源。 |
|
||||
| [IsRegistered](IsRegistered.md) | 查询当前状态。 |
|
||||
| [GetRegisteredTypes](GetRegisteredTypes.md) | 获取相关状态或对象。 |
|
||||
当前答案就是交给 `ComponentFactoryRegistry`。它保存组件类型名与工厂函数的映射,并按需调用 `GameObject::AddComponent<T>()` 创建实例。
|
||||
|
||||
## 当前实现行为
|
||||
|
||||
### 1. 这是一个单例式全局注册表
|
||||
|
||||
- 使用 [Get](Get.md) 获取全局唯一实例
|
||||
- 构造函数里完成内建组件的预注册
|
||||
- 存储结构是 `unordered_map<string, CreateComponentFn>` 加一个注册顺序数组
|
||||
|
||||
### 2. 当前预注册组件
|
||||
|
||||
按 `engine/src/Components/ComponentFactoryRegistry.cpp` 当前实现,默认注册了:
|
||||
|
||||
- `Camera`
|
||||
- `Light`
|
||||
- `AudioSource`
|
||||
- `AudioListener`
|
||||
- `MeshFilter`
|
||||
- `MeshRenderer`
|
||||
- `ScriptComponent`
|
||||
|
||||
`Transform` 没有注册,这不是遗漏,而是当前设计决定:`TransformComponent` 由 `GameObject` 构造时内建创建,不通过工厂补建。
|
||||
|
||||
### 3. 工厂真正做的事情
|
||||
|
||||
内建工厂函数最终调用的是:
|
||||
|
||||
`gameObject->AddComponent<T>()`
|
||||
|
||||
所以它继承了 `GameObject::AddComponent<T>()` 的所有现实语义,包括:
|
||||
|
||||
- 只负责创建并挂接组件
|
||||
- 不会自动补发 `Awake()`、`Start()` 或 `OnEnable()`
|
||||
|
||||
这一点对理解场景加载后的生命周期非常关键。
|
||||
|
||||
## 注册顺序语义
|
||||
|
||||
`RegisterFactory()` 当前使用 `insert_or_assign`:
|
||||
|
||||
- 新类型会加入 `m_registrationOrder`
|
||||
- 已存在类型会被替换工厂函数
|
||||
- 替换已有类型时不会重复追加到顺序数组
|
||||
|
||||
因此 [GetRegisteredTypes](GetRegisteredTypes.md) 返回的是“首次注册顺序”,不是 map key 的排序结果。
|
||||
|
||||
## 与 Scene 反序列化的关系
|
||||
|
||||
当前 `Scene::DeserializeFromString()` 的流程大致是:
|
||||
|
||||
1. 创建 `GameObject`
|
||||
2. 读出 `transform` payload,恢复内建 `Transform`
|
||||
3. 对每条 `component=<type>;payload` 记录调用 `ComponentFactoryRegistry::CreateComponent()`
|
||||
4. 让新组件执行各自的 `Deserialize()`
|
||||
5. 最后再恢复父子关系
|
||||
|
||||
这条链路解释了两个常见现象:
|
||||
|
||||
- 只有已注册组件类型才能从场景文本成功还原
|
||||
- 反序列化路径并不会自动把组件送入完整运行时生命周期
|
||||
|
||||
## 线程语义
|
||||
|
||||
- 当前实现没有加锁。
|
||||
- 注册和查询都应视为非线程安全操作。
|
||||
- 典型使用方式是在初始化阶段完成注册,在场景加载阶段只读查询。
|
||||
|
||||
## 当前实现限制
|
||||
|
||||
- 只支持基于字符串类型名的简单工厂映射,没有版本迁移、字段升级或 schema 管理层。
|
||||
- 反序列化后不会自动补发 `Awake()`/`Start()`。
|
||||
- 没有发现针对自定义组件热注册冲突、卸载或线程安全的额外保护。
|
||||
|
||||
## 推荐使用方式
|
||||
|
||||
1. 内建组件依赖默认注册即可。
|
||||
2. 自定义组件如果要参与场景反序列化,必须在加载前完成注册。
|
||||
3. 不要把它当成完整反射系统;它只是“名字到构造函数”的桥接层。
|
||||
|
||||
## 相关方法
|
||||
|
||||
- [Get](Get.md)
|
||||
- [RegisterFactory](RegisterFactory.md)
|
||||
- [CreateComponent](CreateComponent.md)
|
||||
- [IsRegistered](IsRegistered.md)
|
||||
- [GetRegisteredTypes](GetRegisteredTypes.md)
|
||||
|
||||
## 相关指南
|
||||
|
||||
- [GameObject-Component Lifecycle And Serialization](../../../_guides/Components/GameObject-Component-Lifecycle-And-Serialization.md)
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [当前目录](../Components.md) - 返回 `Components` 平行目录
|
||||
- [API 总索引](../../../main.md) - 返回顶层索引
|
||||
- [当前模块](../Components.md)
|
||||
- [GameObject](../GameObject/GameObject.md)
|
||||
- [Scene](../../Scene/Scene/Scene.md)
|
||||
- [API 总索引](../../../main.md)
|
||||
|
||||
Reference in New Issue
Block a user