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

5.2 KiB

name description
simulation-development 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.