using Unity.Burst; using Unity.Entities; using Unity.Mathematics; using Unity.NetCode; namespace ProjectM.Simulation { /// /// Derives the LOCAL enableable gate from the replicated every predicted /// tick (Dead == Health.Current <= 0). Runs in BOTH worlds inside /// , BEFORE movement/aim/fire, so a dead player is excluded from /// those systems (which query .WithDisabled<Dead>()) on the server AND the owner-predicting client. /// Because it is a pure function of the already-replicated, reconciled Health (the same derive-don't-replicate /// pattern as ), the gate is identical across server, owner-client, and rollback /// — no replicated enabled bit required. Also zeroes while dead so /// the kinematic character holds still (the movement system is skipped and would otherwise coast on stale /// velocity). The authoritative recovery (Health refill + reposition) is owned server-side by /// PlayerRespawnSystem. Visits dead players too via .WithPresent<Dead>() (required to write /// the enabled bit on an entity whose Dead is currently disabled). /// [UpdateInGroup(typeof(PredictedSimulationSystemGroup))] [UpdateBefore(typeof(PlayerControlSystem))] [UpdateBefore(typeof(PlayerAimSystem))] [BurstCompile] public partial struct PlayerDeathStateSystem : ISystem { [BurstCompile] public void OnUpdate(ref SystemState state) { foreach (var (health, control, deadEnabled) in SystemAPI.Query, RefRW, EnabledRefRW>() .WithAll() .WithPresent()) { bool isDead = health.ValueRO.Current <= 0f; deadEnabled.ValueRW = isDead; if (isDead) control.ValueRW.MoveVelocity = float3.zero; } } } }