vampire-like/skills/simulation-development/SKILL.md

103 lines
5.2 KiB
Markdown

---
name: simulation-development
description: Maintain and extend VampireLike SimulationWorld (P2 baseline). Use for Simulation data contracts, lifecycle sync, Job/Burst pipeline, collision settlement, and rollback-safe runtime switches.
---
# Simulation Development
## Quick Start
1. Read the design spec first: `./references/SimulationDevelopmentSkill.md`.
2. If performance conclusions change, sync evidence to `../../docs/P2 Job System + Burst 落地.md`.
3. Classify change scope before coding:
- `SimData/JobData` contracts
- lifecycle sync (`SimulationWorld.EntitySync`)
- Job/Burst execution pipeline (`SimulationWorld.EnemyJobs`, `SimulationWorld.ProjectileJobs`)
- collision query/settlement semantics
- presentation write-back (`SimulationWorld.Presentation`)
4. Decide rollback behavior up front:
- `UseSimulationMovement` off path
- `UseJobSimulation` off path
5. Add/adjust both EditMode and PlayMode regression tests.
## Source Map
- Simulation core: `../../Assets/GameMain/Scripts/Simulation/SimulationWorld.cs`
- Job data channel: `../../Assets/GameMain/Scripts/Simulation/SimulationWorld.JobDataChannel.cs`
- Enemy jobs: `../../Assets/GameMain/Scripts/Simulation/SimulationWorld.EnemyJobs.cs`
- Projectile jobs: `../../Assets/GameMain/Scripts/Simulation/SimulationWorld.ProjectileJobs.cs`
- Lifecycle sync: `../../Assets/GameMain/Scripts/Simulation/SimulationWorld.EntitySync.cs`
- Presentation sync: `../../Assets/GameMain/Scripts/Simulation/SimulationWorld.Presentation.cs`
- Target selection index: `../../Assets/GameMain/Scripts/Simulation/SimulationWorld.TargetSelectionSpatialIndex.cs`
- Tick context: `../../Assets/GameMain/Scripts/Simulation/SimulationTickContext.cs`
- Index binding: `../../Assets/GameMain/Scripts/Simulation/EntityBinding.cs`
- Battle entry: `../../Assets/GameMain/Scripts/Procedure/Game/GameStateBattle.cs`
- Battle state gate: `../../Assets/GameMain/Scripts/Procedure/Game/ProcedureGame.cs`
- Damage/collision utility: `../../Assets/GameMain/Scripts/Utility/AIUtility.cs`
- Global component init: `../../Assets/GameMain/Scripts/Base/GameEntry.Custom.cs`
- Enemy old path gate:
- `../../Assets/GameMain/Scripts/Entity/EntityLogic/Enemy/MeleeEnemy.cs`
- `../../Assets/GameMain/Scripts/Entity/EntityLogic/Enemy/RemoteEnemy.cs`
- Regression tests:
- `../../Assets/Tests/Simulation/EditMode/SimulationWorldTickTests.cs`
- `../../Assets/Tests/Simulation/PlayMode/SimulationWorldPlayModeTests.cs`
## Non-Negotiable Invariants
- Maintain `EntityId <-> SimulationIndex` consistency.
- Use swap-back removal (`move last -> remove last -> remap index`).
- Keep lifecycle registration/removal inside `EntitySync` event flow; do not double-write containers from gameplay code.
- Keep logic/presentation boundary:
- Simulation computes logical outputs.
- Presentation writes back `Transform`.
- Keep A/B rollback path (`UseSimulationMovement`/`UseJobSimulation`).
- `SetUseSimulationMovement` and `SetUseJobSimulation` must not hot-switch during `Battle`.
- Keep area query snapshot semantics (`SourceWasActiveAtQueryTime`) intact.
- Keep dodge semantics using `Value` (additive), not `Percent`.
- Avoid new managed allocations in Tick hot paths.
## Change Recipes
### Add or Change SimData Fields
1. Update target structs in `Simulation/SimData/` and Job channel structs.
2. Populate defaults in `Create*InitialSimData` / lifecycle registration path.
3. Apply runtime updates in simulation stages.
4. Consume visual fields in `Presentation` only.
5. Ensure backward compatibility when `UseSimulationMovement` is off.
### Extend Job/Burst Pipeline
1. Keep deterministic stage ownership (Build/Schedule/Complete/Commit).
2. Preserve state semantics; avoid UI/audio/effect side effects in simulation loops.
3. Keep `ProfilerMarker` coverage for new or changed stages.
4. Keep hot paths data-driven (no direct `Transform` reads/writes).
### Modify Collision / Area Query Behavior
1. Treat broad phase candidate generation and main-thread settlement as separate steps.
2. Preserve `MaxTargets` semantics across player + enemy candidates.
3. If adding query metadata, flow it through:
- request buffer -> collision query input -> candidate -> settlement.
4. Keep area-source snapshot behavior and avoid runtime-state race regressions.
### Add or Adjust Runtime Switches
1. Define exact effective timing (`Battle` or out-of-`Battle`) before implementation.
2. For high-risk switches, enforce out-of-battle-only changes.
3. Provide clear warning logs for ignored runtime switch attempts.
## Validation Checklist
- `UseSimulationMovement = false` and `true` both run correctly.
- `UseJobSimulation = false` and `true` both run correctly under simulation mode.
- No duplicate registration or stale index after entity hide/destroy.
- Battle loop remains stable (`Battle -> LevelUp -> Shop -> Battle`).
- No new per-frame GC spikes in hot paths.
- Main flow has no new Error/Exception logs.
- Keep these regression tests green in both EditMode and PlayMode:
- `TickProjectiles_LimitsCandidatesToMaxTargets_IncludingPlayerCandidate`
- `SetUseSimulationAndJob_AreIgnored_WhenBattleStateIsActive`
- `EnqueueAreaQuery_CapturesInactiveSourceSnapshot_WhenSourceEntityUnavailable`
- Update `./references/SimulationDevelopmentSkill.md` when contracts, boundaries, or rules change.