4.6 KiB
Component
命名空间: XCEngine::Components
类型: class (abstract base)
头文件: XCEngine/Components/Component.h
描述: 所有挂载式组件的抽象基类,定义统一的生命周期钩子、归属对象访问和启用状态控制。
角色概述
Component 是 GameObject 组合模型里的最小行为单元。它本身不拥有场景对象,也不负责更新循环;真正的驱动者是 GameObject 和 Scene。Component 主要提供三类能力:
- 生命周期钩子:
Awake、Start、Update、FixedUpdate、LateUpdate、OnEnable、OnDisable、OnDestroy。 - 归属关系访问:
GetGameObject()、transform()、GetScene()。 - 运行期开关:
IsEnabled()、SetEnabled()。
这和 Unity 的 Component/Behaviour 设计思路相近,但当前实现更轻:基类默认几乎全部是空实现,没有调度器、执行顺序系统或线程隔离层。
生命周期
Component 的生命周期由宿主 GameObject 驱动,而不是由组件自身驱动。
Awake()、Start()、Update()、FixedUpdate()、LateUpdate()只有在GameObject/Scene主动调用时才会发生。SetEnabled()会根据“组件启用状态”和“对象是否在层级中激活”共同决定是否触发OnEnable()或OnDisable()。OnDestroy()由GameObject::Destroy()或Scene::DestroyGameObject()路径触发;基类析构函数本身不补发销毁回调。
按当前实现,直接对一个已经运行中的 GameObject 调用 AddComponent<T>(),不会自动调用新组件的 Awake()、Start() 或 OnEnable()。如果你的运行时逻辑依赖这些阶段,需要明确安排调用时机。
所有权与归属
Component不直接暴露 public 构造 ownership;实例通常由GameObject持有在std::unique_ptr<Component>容器中。m_gameObject由GameObject::AddComponent<T>()在挂接时回填。GetGameObject()仅返回裸指针,不转移所有权。GetScene()只是经由宿主对象转发访问场景。
transform() 的前提条件比 GetScene() 更严格。当前实现直接解引用 m_gameObject->GetTransform(),没有空指针保护,因此它只适用于“已经成功挂到某个 GameObject 上”的组件。
启用状态语义
SetEnabled(bool) 的有效状态不是单纯的 m_enabled,而是:
component enabled && gameObject active in hierarchy
这意味着:
- 对挂在非激活对象上的组件执行
SetEnabled(true),不会立刻触发OnEnable()。 - 当对象重新进入激活层级时,
GameObject会补发OnEnable()。 - 如果启用状态前后“有效可用性”没有变化,
SetEnabled()会直接返回,不重复触发回调。
这套行为已被 tests/Components/test_component.cpp 覆盖验证。
序列化语义
- 基类
Serialize(std::ostream&)默认是 no-op。 - 基类
Deserialize(std::istream&)默认是 no-op。
因此,组件是否能被场景保存/加载,完全取决于具体子类是否覆写这两个函数。文档阅读时不要默认所有组件都可持久化。
线程语义
- 当前实现没有内部加锁。
- 文档和源码都没有提供跨线程读写同一组件实例的安全保证。
- 按当前调用关系,生命周期和大多数组件访问应默认视为主线程/场景线程语义。
对音频类组件来说,虽然会与 AudioSystem 交互,但这不代表 Component 基类本身具备线程同步能力。
当前实现限制
transform()对未附着组件是未定义用法,因为实现里没有 null check。- 基类不区分“已构造”“已挂接”“已进入场景”“已启动”等更细粒度状态。
- 没有统一的反射、属性枚举或编辑器元数据系统;文档页只能按实际 public API 解释。
相关方法
- Awake
- Start
- Update
- FixedUpdate
- LateUpdate
- OnEnable
- OnDisable
- OnDestroy
- GetGameObject
- transform
- GetScene
- IsEnabled
- SetEnabled
- Serialize
- Deserialize