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

3.5 KiB
Raw Blame History

Script 组件分析

组件职责

Script.* 负责:

  • 脚本类型注册与脚本实例创建;
  • script_id 生命周期管理;
  • 脚本逐帧更新;
  • 脚本对 Transform 的延迟写回。

核心存储

Script.cpp 的关键结构:

  • entity_scripts:活跃脚本实例池
  • id_mappingscript_id 索引到实例池下标
  • generations + free_ids:脚本 ID 代数与复用队列
  • transform_cache:脚本写变换的缓存数组
  • cache_mapTransform 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 存储细节隔离。

三条主线时序图(注册、生命周期、缓存提交)

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