vampire-like/skills/simulation-development/references/SimulationDevelopmentSkill.md

201 lines
6.9 KiB
Markdown
Raw 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.

# Simulation Development Skill (VampireLike)
## 目标
本文件是 SimulationWorld 的正式设计说明和扩展开发规范。
后续在 Simulation 相关模块做功能扩展、性能优化、回归修复时,统一按本规范执行。
## 适用范围
- 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 已是战斗核心调度层。
## 模块分层
SimulationWorld 使用 partial 拆分,职责如下:
- 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和命中表现事件消费。
## 运行时执行链路
1. GameStateBattle.OnUpdate
- 先执行 EnemyManager.OnUpdate
- 再执行 SimulationWorld.Tick
2. SimulationWorld.Tick
- UseSimulationMovement = false直接返回完全回退旧链路
- UseSimulationMovement = true 且 UseJobSimulation = false走主线程敌人仿真
- UseSimulationMovement = true 且 UseJobSimulation = true走 Job/Burst 总链路
3. SimulationWorld.LateUpdate
- 调用 Presentation.OnLateUpdate
- 统一写回 Enemy/Projectile 表现
## 核心数据契约
### 主容器
- List<EnemySimData> _enemies
- List<ProjectileSimData> _projectiles
- List<PickupSimData> _pickups
### 绑定关系
- EntityBinding 维护 EntityId <-> SimulationIndex 双向映射。
- 删除必须使用 swap-back
- 尾元素覆盖删除位
- RemapIndex
- RemoveAt(last)
### Job 通道
- EnemyJobInput/Output
- ProjectileJobInput/Output
- CollisionQuery/CollisionCandidate
- NativeParallelMultiHashMap互斥桶、碰撞桶、目标桶
统一规则:
- Allocator.Persistent 分配
- Initialize/Dispose 集中管理
- Clear 只清容器,不破坏生命周期
## 不可破坏的设计约束
### 生命周期单入口
仿真容器增删只能由 EntitySync 驱动。
禁止在 Enemy/Weapon/Projectile 业务代码中直接改仿真容器。
### 逻辑与表现边界
- Simulation 只产出逻辑数据,不直接写 Transform。
- Transform 写回只能在 Presentation。
- 命中表现通过事件缓冲在主线程提交。
### 开关和回滚
- UseSimulationMovement总开关支持一键回滚。
- UseJobSimulationJob 开关,支持 P1.5/ P2 对照。
- UseBurstJobsBurst 开关。
### 生效时机约束(重要)
- SetUseSimulationMovement / SetUseJobSimulation 在 Battle 中会被忽略。
- 这两个开关不支持战斗内热切换,只允许战斗外修改生效。
## 敌人和投射物执行模型
### 敌人Job
固定阶段:
- BuildInput
- Move
- Separation
- Commit
约束:
- 热路径禁止 LINQ 和托管分配
- 不读写 Transform
- 阶段必须可独立 Profile
### 投射物Job
包含:
- 移动更新
- 寿命和越界回收
- Broad Phase 候选构建
- 主线程命中结算和回收
## 碰撞和伤害结算规范
### Broad Phase
候选由 _collisionQueryInputs + _enemyCollisionBuckets 计算。
MaxTargets 必须覆盖“玩家候选 + 敌人候选”的总量。
### Area Query 快照语义
- 入队时记录 SourceWasActiveAtQueryTime。
- 结算按快照判定来源有效性,避免查询后状态变化导致误判。
### 主线程结算
- Projectile 命中:按 ImpactData + AIUtility.CalcDamageHP。
- Area 命中:调用 AIUtility.PerformCollision(target, source, true)。
### 伤害公式约束
AIUtility.CalcDamageHP
- 闪避使用 dodgeStat.Value加算语义不使用 Percent。
- 攻击: (attack + AttackStat.Value) * AttackStat.Percent
- 防御: (damage - DefenseStat.Value) / DefenseStat.Percent
- 最终伤害最小值为 1。
## 已修复问题(纳入长期约束)
1. 闪避语义修正:使用 Value 而非 Percent。
2. UseSimulationMovement / UseJobSimulation 战斗内禁止热切换。
3. MaxTargets 统计覆盖玩家候选,避免超额候选。
4. Area 查询引入来源活跃快照并按快照结算。
后续改动若触碰这些路径,必须保持行为不回退。
## 扩展开发 SOP
### Step 0定义模式和回滚
- 明确功能在哪条路径生效Simulation / Job / Burst
- 明确开关关闭后的回退行为。
### Step 1扩数据
- 先改 SimData 和 JobData。
- 再改 CreateInitialSimData 与转换函数。
### Step 2接生命周期
- 只在 EntitySync 增加注册/反注册。
- 保持 group 到容器映射清晰。
### Step 3接执行阶段
- 优先放入现有阶段Build/Schedule/Commit
- 新阶段必须补 ProfilerMarker。
### Step 4接结算和表现
- 逻辑结算收口到主线程。
- 表现写回放在 Presentation。
### Step 5补测试
EditMode 和 PlayMode 同步补回归,至少覆盖:
- 行为正确性
- 开关路径
- 索引稳定性
- 新增边界条件
### Step 6更新文档
- 更新本文件。
- 需要性能结论时,同步更新 docs/P2 Job System + Burst 落地.md。
## 测试命令
- 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
## 关键回归用例(必须保留)
- TickEnemies_MatchesOutput_WhenBurstJobsToggled
- TryGetNearestEnemyEntityId_SelectsNearestBucketCandidate_WhenJobSimulationEnabled
- TickProjectiles_LimitsCandidatesToMaxTargets_IncludingPlayerCandidate
- SetUseSimulationAndJob_AreIgnored_WhenBattleStateIsActive
- EnqueueAreaQuery_CapturesInactiveSourceSnapshot_WhenSourceEntityUnavailable
对应文件:
- Assets/Tests/Simulation/EditMode/SimulationWorldTickTests.cs
- Assets/Tests/Simulation/PlayMode/SimulationWorldPlayModeTests.cs
## P2 验收口径
- 3k 敌人下 Main Thread 明显下降(目标 >= 30%)。
- 战斗持续帧 GC Alloc 接近 0。
- Battle -> LevelUp -> Shop -> Battle 循环稳定。
## 提交前门禁清单
- 关闭 UseSimulationMovement 是否完全回退旧链路。
- EntityBinding 是否保持双向一致,删除后是否正确 remap。
- Job 容器是否无泄漏Persistent 都可 Dispose
- 是否引入新热路径 GCLINQ、临时集合、装箱
- 是否破坏“战斗内不热切换 UseSimulationMovement/UseJobSimulation”。
- 是否同步更新测试和本设计文档。