remove open spec skills
This commit is contained in:
@@ -1,200 +1,311 @@
|
||||
# Simulation Development Skill (VampireLike)
|
||||
# SimulationWorld Architecture Specification
|
||||
|
||||
## 目标
|
||||
本文件是 SimulationWorld 的正式设计说明和扩展开发规范。
|
||||
后续在 Simulation 相关模块做功能扩展、性能优化、回归修复时,统一按本规范执行。
|
||||
## 文档定位
|
||||
本文件是 `SimulationWorld` 的架构规范与扩展开发约束。
|
||||
|
||||
用途分为两部分:
|
||||
- 作为当前 `SimulationWorld` 实现的架构总览,说明模块职责、依赖边界、运行链路和数据所有权。
|
||||
- 作为后续扩展、重构、性能优化和回归修复时的约束文档,防止破坏核心不变量。
|
||||
|
||||
文档与实现冲突时,当前分支源码优先;提交前必须同步修正文档。
|
||||
|
||||
## 适用范围
|
||||
- Assets/GameMain/Scripts/Simulation/*
|
||||
- Assets/GameMain/Scripts/Procedure/Game/GameStateBattle.cs
|
||||
- Assets/GameMain/Scripts/Procedure/Game/ProcedureGame.cs
|
||||
- Assets/GameMain/Scripts/Utility/AIUtility.cs
|
||||
- Assets/Tests/Simulation/EditMode/*
|
||||
- Assets/Tests/Simulation/PlayMode/*
|
||||
- `Assets/GameMain/Scripts/Simulation/*`
|
||||
- `Assets/GameMain/Scripts/Procedure/Game/GameStateBattle.cs`
|
||||
- `Assets/GameMain/Scripts/Procedure/Game/ProcedureGame.cs`
|
||||
- `Assets/GameMain/Scripts/Utility/AIUtility.cs`
|
||||
- `Assets/Tests/Simulation/EditMode/*`
|
||||
- `Assets/Tests/Simulation/PlayMode/*`
|
||||
|
||||
当前状态:P2 Job/Burst 主体已完成,SimulationWorld 已是战斗核心调度层。
|
||||
## 架构目标
|
||||
- 将战斗中的敌人、投射物、掉落物运行时状态收口到统一仿真容器。
|
||||
- 将热路径逻辑与 Unity 表现层解耦,避免在仿真阶段直接读写 `Transform`。
|
||||
- 为 Job/Burst 提供稳定的数据通道、生命周期管理和主线程结算收口点。
|
||||
- 保持 `SimulationWorld` 对外是单一战斗调度入口,而不是分散的业务入口集合。
|
||||
- 保证扩展新仿真对象或新碰撞规则时,能够沿着既有管线接入,而不是旁路修改。
|
||||
|
||||
## 模块分层
|
||||
SimulationWorld 使用 partial 拆分,职责如下:
|
||||
## 非目标
|
||||
- 不负责完整战斗规则定义。伤害公式、碰撞业务语义仍由 `AIUtility` 和实体逻辑承担。
|
||||
- 不负责实体创建策略。实体创建与隐藏仍由外部流程和 Entity 系统负责。
|
||||
- 不追求全局 ECS 化。本模块仍以 `SimulationWorld + partial + Native 容器` 为中心组织。
|
||||
- 不在 Job 中直接驱动表现层、事件系统或 Unity 对象生命周期。
|
||||
|
||||
- SimulationWorld.cs
|
||||
- 开关、主容器、绑定、主 Tick 入口。
|
||||
- SimulationWorld.EntitySync.cs
|
||||
- 实体 Show/Hide 到仿真容器的生命周期同步。
|
||||
- SimulationWorld.EnemyJobs.cs
|
||||
- 敌人移动和互斥分离的 Job/Burst 链路。
|
||||
- SimulationWorld.ProjectileJobs.cs
|
||||
- 投射物移动、寿命、碰撞候选、主线程结算。
|
||||
- SimulationWorld.JobDataChannel.cs
|
||||
- Native 容器、拷贝转换、容量管理、运行时统计。
|
||||
- SimulationWorld.TargetSelectionSpatialIndex.cs
|
||||
- 目标选择空间索引(最近敌人查询)。
|
||||
- SimulationWorld.Presentation.cs
|
||||
- 表现层写回(Transform)和命中表现事件消费。
|
||||
## 外部依赖与系统边界
|
||||
`SimulationWorld` 处于战斗流程中层,位于 `GameStateBattle` 和具体实体逻辑之间。
|
||||
|
||||
## 运行时执行链路
|
||||
1. GameStateBattle.OnUpdate
|
||||
- 先执行 EnemyManager.OnUpdate
|
||||
- 再执行 SimulationWorld.Tick
|
||||
上游依赖:
|
||||
- `GameStateBattle.OnUpdate` 驱动每帧 `Tick`。
|
||||
- `GameEntry.Event` 提供实体显示/隐藏事件,用于同步仿真容器生命周期。
|
||||
- `GameEntry.Entity` 提供实体查询、隐藏和表现事件消费。
|
||||
|
||||
2. SimulationWorld.Tick
|
||||
- UseSimulationMovement = false:直接返回(完全回退旧链路)
|
||||
- UseSimulationMovement = true 且 UseJobSimulation = false:走主线程敌人仿真
|
||||
- UseSimulationMovement = true 且 UseJobSimulation = true:走 Job/Burst 总链路
|
||||
下游协作:
|
||||
- `AIUtility` 负责伤害与碰撞业务结算。
|
||||
- Enemy/Projectile/Drop 实体提供初始化所需运行时数据。
|
||||
- Presentation 子模块负责把仿真结果写回表现层。
|
||||
|
||||
3. SimulationWorld.LateUpdate
|
||||
- 调用 Presentation.OnLateUpdate
|
||||
- 统一写回 Enemy/Projectile 表现
|
||||
边界要求:
|
||||
- 外部业务代码不得直接增删 `_enemies`、`_projectiles`、`_pickups`。
|
||||
- 外部业务代码不得绕过 `SimulationWorld` 直接维护仿真索引。
|
||||
- `SimulationWorld` 不直接拥有实体生成权,只消费实体生命周期事件。
|
||||
|
||||
## 核心数据契约
|
||||
## 模块结构
|
||||
`SimulationWorld` 使用 `partial` 拆分,职责按以下边界划分:
|
||||
|
||||
- `SimulationWorld.cs`
|
||||
- 核心组件入口、主状态容器、基础依赖、Unity 生命周期入口。
|
||||
- `SimulationWorld.SimEntityState.cs`
|
||||
- 敌人、投射物、掉落物的仿真态创建、更新、删除和清空。
|
||||
- `SimulationWorld.EntitySync.cs`
|
||||
- 监听实体 show/hide 事件,将实体生命周期映射到仿真容器。
|
||||
- `DataChannel/SimulationWorld.JobDataChannel.cs`
|
||||
- Native 容器持有、初始化、清理、容量准备、仿真数据到 Job 数据的转换。
|
||||
- `Jobs/SimulationWorld.EnemyJobs.cs`
|
||||
- 每帧仿真主编排、敌人移动与互斥分离 Job 调度。
|
||||
- `Jobs/SimulationWorld.ProjectileJobs.cs`
|
||||
- 投射物移动、寿命处理、越界回收。
|
||||
- `Jobs/SimulationWorld.CollisionPipeline.cs`
|
||||
- 投射物与区域碰撞查询构建、候选筛选、主线程命中结算。
|
||||
- `SimulationWorld.TargetSelectionSpatialIndex.cs`
|
||||
- 敌人目标选择空间索引。
|
||||
- `Presentation/SimulationWorld.TransformSync.cs`
|
||||
- `LateUpdate` 表现写回。
|
||||
- `Presentation/SimulationWorld.HitPresentation.cs`
|
||||
- 命中事件的表现消费桥。
|
||||
|
||||
## 核心数据所有权
|
||||
### 主容器
|
||||
- List<EnemySimData> _enemies
|
||||
- List<ProjectileSimData> _projectiles
|
||||
- List<PickupSimData> _pickups
|
||||
- `_enemies`
|
||||
- `_projectiles`
|
||||
- `_pickups`
|
||||
|
||||
这些容器是真实仿真态所有者。Job 输入输出缓冲只是当前帧的镜像通道,不是持久源数据。
|
||||
|
||||
### 绑定关系
|
||||
- EntityBinding 维护 EntityId <-> SimulationIndex 双向映射。
|
||||
- 删除必须使用 swap-back:
|
||||
- 尾元素覆盖删除位
|
||||
- RemapIndex
|
||||
- RemoveAt(last)
|
||||
- `EntityBinding` 维护 `EntityId <-> SimulationIndex` 双向映射。
|
||||
- 容器删除使用 `swap-back`。
|
||||
- 发生尾元素覆盖时,必须同步 `RemapIndex`。
|
||||
- 删除完成后再 `Unbind`,避免索引悬挂。
|
||||
|
||||
### Job 通道
|
||||
- EnemyJobInput/Output
|
||||
- ProjectileJobInput/Output
|
||||
- CollisionQuery/CollisionCandidate
|
||||
- NativeParallelMultiHashMap(互斥桶、碰撞桶、目标桶)
|
||||
### Native 容器
|
||||
- Job 通道一律使用 `Allocator.Persistent`。
|
||||
- 生命周期由 `InitializeJobDataChannels` / `DisposeJobDataChannels` 集中管理。
|
||||
- 帧间复用时使用 `Clear`,不允许用临时重建替代正常复用。
|
||||
- Job 数据与主容器数据之间的转换必须集中在 `JobDataChannel` 侧完成。
|
||||
|
||||
统一规则:
|
||||
- Allocator.Persistent 分配
|
||||
- Initialize/Dispose 集中管理
|
||||
- Clear 只清容器,不破坏生命周期
|
||||
## 生命周期模型
|
||||
### 实体进入仿真
|
||||
统一由 `EntitySync` 监听实体显示事件后触发:
|
||||
- Enemy group -> `RegisterEnemyLifecycle`
|
||||
- Drop group -> `RegisterPickupLifecycle`
|
||||
- Bullet / Projectile / EnemyProjectile group -> `RegisterProjectileLifecycle`
|
||||
|
||||
## 不可破坏的设计约束
|
||||
### 生命周期单入口
|
||||
仿真容器增删只能由 EntitySync 驱动。
|
||||
禁止在 Enemy/Weapon/Projectile 业务代码中直接改仿真容器。
|
||||
### 实体退出仿真
|
||||
统一由 `EntitySync` 监听实体隐藏事件后触发:
|
||||
- Enemy -> `UnregisterEnemyLifecycle`
|
||||
- Drop -> `UnregisterPickupLifecycle`
|
||||
- Projectile 相关 group -> `UnregisterProjectileLifecycle`
|
||||
|
||||
### 逻辑与表现边界
|
||||
- Simulation 只产出逻辑数据,不直接写 Transform。
|
||||
- Transform 写回只能在 Presentation。
|
||||
- 命中表现通过事件缓冲在主线程提交。
|
||||
### 清场
|
||||
`ClearSimulationState` 负责:
|
||||
- 清空主容器
|
||||
- 清空投射物回收与结算缓存
|
||||
- 清空区域碰撞请求与命中缓存
|
||||
- 清空 Job 通道
|
||||
- 清空全部 `EntityBinding`
|
||||
|
||||
### 开关和回滚
|
||||
- UseSimulationMovement:总开关,支持一键回滚。
|
||||
- UseJobSimulation:Job 开关,支持 P1.5/ P2 对照。
|
||||
- UseBurstJobs:Burst 开关。
|
||||
## 运行时执行链路
|
||||
### 帧级入口
|
||||
1. `GameStateBattle.OnUpdate`
|
||||
2. `_enemyManager.OnUpdate(...)`
|
||||
3. `SimulationWorld.Tick(...)`
|
||||
4. `SimulationWorld.LateUpdate()`
|
||||
|
||||
### 生效时机约束(重要)
|
||||
- SetUseSimulationMovement / SetUseJobSimulation 在 Battle 中会被忽略。
|
||||
- 这两个开关不支持战斗内热切换,只允许战斗外修改生效。
|
||||
|
||||
## 敌人和投射物执行模型
|
||||
### 敌人(Job)
|
||||
固定阶段:
|
||||
- BuildInput
|
||||
- Move
|
||||
- Separation
|
||||
- Commit
|
||||
### Tick 总流程
|
||||
`SimulationWorld.Tick` 是战斗仿真的唯一主入口。
|
||||
|
||||
约束:
|
||||
- 热路径禁止 LINQ 和托管分配
|
||||
- 不读写 Transform
|
||||
- 阶段必须可独立 Profile
|
||||
- 当 `UseSimulationMovement == false` 时,直接返回。
|
||||
- `Tick` 只负责逻辑仿真与结算,不直接写 `Transform`。
|
||||
|
||||
### 投射物(Job)
|
||||
包含:
|
||||
- 移动更新
|
||||
- 寿命和越界回收
|
||||
- Broad Phase 候选构建
|
||||
- 主线程命中结算和回收
|
||||
### 每帧仿真管线
|
||||
当前实现的标准顺序为:
|
||||
1. Early Return
|
||||
- `DeltaTime <= 0` 时只清理碰撞临时通道和统计。
|
||||
2. BuildInput
|
||||
- 将 `_enemies` / `_projectiles` 同步为 Job 输入。
|
||||
- 准备敌人输出、投射物输出、碰撞查询缓冲。
|
||||
3. StateUpdate
|
||||
- 调度敌人移动 Job。
|
||||
- 调度投射物移动 Job。
|
||||
4. Schedule
|
||||
- 按需调度敌人互斥分离 Job。
|
||||
- 合并敌人与投射物 Job 依赖。
|
||||
5. Complete
|
||||
- 等待本帧仿真 Job 完成。
|
||||
6. Collision
|
||||
- 构建碰撞查询。
|
||||
- 构建敌人碰撞桶。
|
||||
- 生成候选并统计。
|
||||
7. WriteBack
|
||||
- 把输出写回主容器。
|
||||
- 在主线程结算碰撞与伤害。
|
||||
- 回收失效投射物。
|
||||
|
||||
## 碰撞和伤害结算规范
|
||||
### Broad Phase
|
||||
候选由 _collisionQueryInputs + _enemyCollisionBuckets 计算。
|
||||
MaxTargets 必须覆盖“玩家候选 + 敌人候选”的总量。
|
||||
### LateUpdate
|
||||
`LateUpdate` 只做表现写回,不做逻辑判定:
|
||||
- 敌人位置/朝向写回
|
||||
- 投射物位置/朝向写回
|
||||
|
||||
### Area Query 快照语义
|
||||
- 入队时记录 SourceWasActiveAtQueryTime。
|
||||
- 结算按快照判定来源有效性,避免查询后状态变化导致误判。
|
||||
## 线程模型与边界
|
||||
### Job/Burst 允许做的事
|
||||
- 读取 Job 输入缓冲
|
||||
- 写入 Job 输出缓冲
|
||||
- 写入 NativeHashMap / NativeList 等碰撞与分桶数据
|
||||
- 执行纯数据计算
|
||||
|
||||
### 主线程结算
|
||||
- Projectile 命中:按 ImpactData + AIUtility.CalcDamageHP。
|
||||
- Area 命中:调用 AIUtility.PerformCollision(target, source, true)。
|
||||
### Job/Burst 禁止做的事
|
||||
- 读写 `Transform`
|
||||
- 操作 GameObject / Entity 生命周期
|
||||
- 调用事件系统
|
||||
- 直接调用 `AIUtility.PerformCollision`
|
||||
- 进行托管分配、LINQ、装箱
|
||||
|
||||
### 伤害公式约束
|
||||
AIUtility.CalcDamageHP:
|
||||
- 闪避使用 dodgeStat.Value(加算语义),不使用 Percent。
|
||||
- 攻击: (attack + AttackStat.Value) * AttackStat.Percent
|
||||
- 防御: (damage - DefenseStat.Value) / DefenseStat.Percent
|
||||
- 最终伤害最小值为 1。
|
||||
### 主线程必须做的事
|
||||
- 应用输出到仿真主容器
|
||||
- 命中结算与伤害计算
|
||||
- 投射物失效回收
|
||||
- 命中表现事件派发
|
||||
- `LateUpdate` 表现写回
|
||||
|
||||
## 已修复问题(纳入长期约束)
|
||||
1. 闪避语义修正:使用 Value 而非 Percent。
|
||||
2. UseSimulationMovement / UseJobSimulation 战斗内禁止热切换。
|
||||
3. MaxTargets 统计覆盖玩家候选,避免超额候选。
|
||||
4. Area 查询引入来源活跃快照并按快照结算。
|
||||
## 子系统约束
|
||||
### 敌人仿真
|
||||
固定接入点:
|
||||
- BuildInput
|
||||
- Movement
|
||||
- Separation
|
||||
- WriteBack
|
||||
|
||||
后续改动若触碰这些路径,必须保持行为不回退。
|
||||
约束:
|
||||
- 敌人状态必须以 `EnemySimData` 为中心流动。
|
||||
- 互斥与移动结果必须先写入输出缓冲,再统一提交。
|
||||
- 与目标选择相关的空间索引脏标记必须在主容器变更时维护。
|
||||
|
||||
## 扩展开发 SOP
|
||||
### Step 0:定义模式和回滚
|
||||
- 明确功能在哪条路径生效(Simulation / Job / Burst)。
|
||||
- 明确开关关闭后的回退行为。
|
||||
### 投射物仿真
|
||||
固定接入点:
|
||||
- BuildInput
|
||||
- Movement
|
||||
- Collision Query
|
||||
- Resolve
|
||||
- Recycle
|
||||
|
||||
### Step 1:扩数据
|
||||
- 先改 SimData 和 JobData。
|
||||
- 再改 CreateInitialSimData 与转换函数。
|
||||
约束:
|
||||
- 投射物生命周期状态必须由 `ProjectileSimData.Active` 和 `State` 共同表达。
|
||||
- 投射物实际隐藏与移除只能在主线程回收阶段完成。
|
||||
|
||||
### 碰撞管线
|
||||
职责:
|
||||
- 构建投射物查询和区域查询
|
||||
- 生成 broad-phase 候选
|
||||
- 在主线程做最终业务结算
|
||||
|
||||
约束:
|
||||
- Broad-phase 只能筛候选,不能替代最终命中判定。
|
||||
- Area Query 必须保留 `SourceWasActiveAtQueryTime` 快照语义。
|
||||
- 候选去重与区域命中去重只能在主线程收口。
|
||||
|
||||
### 目标选择空间索引
|
||||
职责:
|
||||
- 提供按位置查询最近敌人的能力。
|
||||
|
||||
约束:
|
||||
- 仅在仿真启用时对外提供结果。
|
||||
- 敌人主容器变更后必须标记脏。
|
||||
- 索引是缓存,不是源数据;源数据仍是 `_enemies`。
|
||||
|
||||
### Presentation
|
||||
职责:
|
||||
- 将仿真层结果写回表现层。
|
||||
- 消费命中表现事件。
|
||||
|
||||
约束:
|
||||
- Presentation 只消费仿真结果,不反向修改仿真逻辑状态。
|
||||
- 任何新增表现都应接在 `Presentation` 子模块,而不是接回 Job 或业务结算热路径。
|
||||
|
||||
## 不可破坏的不变量
|
||||
### 生命周期单入口
|
||||
仿真容器的增删必须只经过 `EntitySync` 和 `SimEntityState`。
|
||||
|
||||
### 数据单一事实来源
|
||||
主容器是持续态事实来源,Job 缓冲只是帧级副本。
|
||||
|
||||
### 逻辑与表现分离
|
||||
逻辑阶段不写 `Transform`,表现阶段不做业务结算。
|
||||
|
||||
### 索引一致性
|
||||
任何 `swap-back` 删除都必须同步 remap,否则视为架构级错误。
|
||||
|
||||
### 主线程结算收口
|
||||
伤害、事件派发、实体隐藏和回收必须回到主线程。
|
||||
|
||||
### 空间索引与碰撞桶是缓存
|
||||
它们可以重建,不可被外部业务当作持久数据依赖。
|
||||
|
||||
## 扩展开发流程
|
||||
### Step 0:判定接入位置
|
||||
先判断新需求属于:
|
||||
- 新仿真态字段
|
||||
- 新执行阶段逻辑
|
||||
- 新碰撞查询类型
|
||||
- 新表现桥接
|
||||
|
||||
不要一开始就直接改 `Tick` 主流程。
|
||||
|
||||
### Step 1:扩状态
|
||||
先补 `SimData`、必要的 Job 输入输出结构和转换逻辑。
|
||||
|
||||
### Step 2:接生命周期
|
||||
- 只在 EntitySync 增加注册/反注册。
|
||||
- 保持 group 到容器映射清晰。
|
||||
如果是新实体类型,先定义 show/hide 到仿真态的映射,再进入执行阶段。
|
||||
|
||||
### Step 3:接执行阶段
|
||||
- 优先放入现有阶段(Build/Schedule/Commit)。
|
||||
- 新阶段必须补 ProfilerMarker。
|
||||
### Step 3:接执行管线
|
||||
优先复用已有阶段;只有确实无法收纳时才新增阶段,并补可观测的 profiler 标记。
|
||||
|
||||
### Step 4:接结算和表现
|
||||
- 逻辑结算收口到主线程。
|
||||
- 表现写回放在 Presentation。
|
||||
### Step 4:接主线程结算
|
||||
需要业务判定、伤害、事件派发、实体隐藏时,一律回主线程收口。
|
||||
|
||||
### Step 5:补测试
|
||||
EditMode 和 PlayMode 同步补回归,至少覆盖:
|
||||
- 行为正确性
|
||||
- 开关路径
|
||||
- 索引稳定性
|
||||
- 新增边界条件
|
||||
### Step 5:接表现
|
||||
视觉写回、命中反馈、临时特效都放在 `Presentation` 侧。
|
||||
|
||||
### Step 6:更新文档
|
||||
- 更新本文件。
|
||||
- 需要性能结论时,同步更新 docs/P2 Job System + Burst 落地.md。
|
||||
### Step 6:补测试
|
||||
至少覆盖:
|
||||
- 正常行为
|
||||
- 空容器和边界条件
|
||||
- 删除后的索引稳定性
|
||||
- 碰撞去重或快照语义
|
||||
- 与旧路径一致的关键行为
|
||||
|
||||
## 测试命令
|
||||
- PlayMode
|
||||
- Unity -batchmode -nographics -projectPath . -runTests -testPlatform PlayMode -testResults Logs/playmode-test-results.xml -logFile Logs/playmode-tests.log
|
||||
- EditMode
|
||||
- Unity -batchmode -nographics -projectPath . -runTests -testPlatform EditMode -testResults Logs/editmode-test-results.xml -logFile Logs/editmode-tests.log
|
||||
### Step 7:更新文档
|
||||
修改模块边界、数据契约、不变量或执行阶段时,必须同步更新本文件。
|
||||
|
||||
## 关键回归用例(必须保留)
|
||||
- TickEnemies_MatchesOutput_WhenBurstJobsToggled
|
||||
- TryGetNearestEnemyEntityId_SelectsNearestBucketCandidate_WhenJobSimulationEnabled
|
||||
- TickProjectiles_LimitsCandidatesToMaxTargets_IncludingPlayerCandidate
|
||||
- SetUseSimulationAndJob_AreIgnored_WhenBattleStateIsActive
|
||||
- EnqueueAreaQuery_CapturesInactiveSourceSnapshot_WhenSourceEntityUnavailable
|
||||
## 回归关注点
|
||||
- `ClearSimulationState` 是否把主容器、缓存和 binding 一并清干净。
|
||||
- 删除路径是否保持 `swap-back + remap` 一致。
|
||||
- Job Native 容器是否有泄漏或容量管理回退。
|
||||
- 是否在热路径引入托管分配。
|
||||
- 是否让表现逻辑重新侵入仿真逻辑。
|
||||
- 是否破坏 Area Query 快照语义。
|
||||
- 是否破坏碰撞候选与命中去重。
|
||||
|
||||
对应文件:
|
||||
- Assets/Tests/Simulation/EditMode/SimulationWorldTickTests.cs
|
||||
- Assets/Tests/Simulation/PlayMode/SimulationWorldPlayModeTests.cs
|
||||
## 测试建议
|
||||
至少保留并持续扩展以下类型的测试:
|
||||
- Tick 行为正确性
|
||||
- 主线程与 Job 管线一致性
|
||||
- 最近敌查询正确性
|
||||
- 投射物候选上限与玩家候选覆盖
|
||||
- Area Query 快照语义
|
||||
- 清场和 Battle 循环稳定性
|
||||
|
||||
## P2 验收口径
|
||||
- 3k 敌人下 Main Thread 明显下降(目标 >= 30%)。
|
||||
- 战斗持续帧 GC Alloc 接近 0。
|
||||
- Battle -> LevelUp -> Shop -> Battle 循环稳定。
|
||||
|
||||
## 提交前门禁清单
|
||||
- 关闭 UseSimulationMovement 是否完全回退旧链路。
|
||||
- EntityBinding 是否保持双向一致,删除后是否正确 remap。
|
||||
- Job 容器是否无泄漏(Persistent 都可 Dispose)。
|
||||
- 是否引入新热路径 GC(LINQ、临时集合、装箱)。
|
||||
- 是否破坏“战斗内不热切换 UseSimulationMovement/UseJobSimulation”。
|
||||
- 是否同步更新测试和本设计文档。
|
||||
## 维护原则
|
||||
如果未来需要继续扩展为多模式仿真开关、更多 Job 管线层级或新的仿真对象类型,应优先维护以下三点:
|
||||
- `Tick` 仍然只有一个主入口
|
||||
- 仿真态生命周期仍然只有一个注册/反注册入口
|
||||
- 主线程结算与表现写回边界不被打穿
|
||||
|
||||
Reference in New Issue
Block a user