# 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
```
