# Script 组件分析 ## 组件职责 `Script.*` 负责: - 脚本类型注册与脚本实例创建; - `script_id` 生命周期管理; - 脚本逐帧更新; - 脚本对 Transform 的延迟写回。 ## 核心存储 `Script.cpp` 的关键结构: - `entity_scripts`:活跃脚本实例池 - `id_mapping`:`script_id` 索引到实例池下标 - `generations + free_ids`:脚本 ID 代数与复用队列 - `transform_cache`:脚本写变换的缓存数组 - `cache_map`:Transform ID 到缓存下标映射 ## 注册机制 脚本工厂注册表: - 类型:`unordered_map` - `register_script(tag, func)` 注册工厂 - `get_script_creator(tag)` 查询工厂 通常由 `REGISTER_SCRIPT` 宏在静态初始化阶段完成注册。 ## 创建流程 `script::create(init_info, entity)`: 1. 校验实体有效与工厂函数有效; 2. 分配 `script_id`(复用或新建); 3. 调用工厂创建脚本实例并压入 `entity_scripts`; 4. 写入 `id_mapping`; 5. 返回 `script::component` 句柄。 ## 删除流程 `script::remove(component c)`: - 校验组件存在; - 用无序删除移除脚本实例; - 修正被交换元素的 `id_mapping`; - 将被删 id 的映射标记为无效。 ## 更新与缓存提交流程 `script::update(dt)` 包含两段: 1. 遍历 `entity_scripts` 执行每个脚本的 `update(dt)`; 2. 若 `transform_cache` 非空,统一调用 `transform::update(...)` 提交后清空。 这使脚本阶段不直接写 Transform 主数组,减少帧内重复写。 ## 脚本写 Transform 的方式 `entity_script::set_rotation/position/...` 的行为是: - 先通过 `get_cache_ptr(entity)` 找到该实体缓存槽; - 设置对应 `flags`; - 写入新值到 cache; - 等待帧末统一提交。 ## 设计特点 - 句柄安全:`script_id` 采用 generation 机制; - 批处理友好:Transform 写入集中提交; - 解耦:脚本逻辑与 Transform 存储细节隔离。 ## 三条主线时序图(注册、生命周期、缓存提交) ```mermaid sequenceDiagram autonumber participant Macro as REGISTER_SCRIPT participant Detail as script::detail participant Registry as script_registry participant Entity as game_entity::entity participant ScriptSys as script::system participant Obj as entity_script participant Cache as transform_cache participant Trans as transform::system rect rgb(236, 248, 255) Note over Macro,Registry: 主线一:脚本类型注册 Macro->>Detail: register_script(tag, creator) Detail->>Registry: insert(tag, creator) Registry-->>Detail: creator 已登记 end rect rgb(239, 252, 240) Note over Entity,ScriptSys: 主线二:脚本实例生命周期 Entity->>ScriptSys: create(init_info, entity) ScriptSys->>ScriptSys: 分配或复用 script_id ScriptSys->>Registry: get_script_creator(tag) Registry-->>ScriptSys: 返回 creator ScriptSys->>Obj: creator(entity) Obj-->>ScriptSys: 生成脚本实例 ScriptSys->>ScriptSys: 写入 entity_scripts 与 id_mapping ScriptSys-->>Entity: 返回 script::component Entity->>ScriptSys: remove(component) ScriptSys->>ScriptSys: erase_unordered + 修正 id_mapping end rect rgb(255, 246, 236) Note over Obj,Trans: 主线三:脚本写变换缓存并帧末提交 ScriptSys->>Obj: update(dt) Obj->>Cache: set_position/rotation/scale... Cache-->>Obj: flags + value 已缓存 ScriptSys->>Trans: transform::update(cache, count) Trans-->>ScriptSys: 写入完成 ScriptSys->>Cache: clear() end ```