Files
DX12/docs/架构分析/Script组件分析.md
2026-03-19 18:27:49 +08:00

120 lines
3.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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<size_t, script_creator>`
- `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
```