Edited 25/11/24 for clarity.
Note that âRollback & Resimulatableâ character controller actions (like moving, jumping, sliding, turning etc) should not be guarded by IsFirstTimeFullyPredictingTick
. IsFirstTimeFullyPredictingTick
should be used exclusively to guard gameplay logic that cannot be rewound (events like entity creation, V&SFX creation etc).
Iâll use a (simplified as ignoring partial ticks) example to illustrate why:
Scenario: A human player presses spacebar (jump) to launch their character controller over a wide hole/ledge. In this example, they are in-flight for about 500ms (30 ticks @ 60Hz). A jump particle and sound effect (V&SFX respectively) is triggered on the first tick that the player predicts leaving the ground.
[1] At some point the client will collect this Spacebar jump input, and store it into their IInputComponentData
. The client will then âclient predictâ this jump for the first time (on the tick the client raised the Spacebar jump input for) by running this tick in the PredictedSimulationSystemGroup
. Therefore, they will calculate a jump velocity, update their character controller, and lets say this logic also triggers the jumping V&SFX (a sound and a particle system at their feet).
[2] However, while mid-air, we can expect this players ClientWorld
to receive many snapshots containing their own character controller ghost. Using default settings, that is ~30 opportunities for this client to receive an updated, server authoritative collection of updated [GhostField]
values for this ghost.
Every time one such snapshot arrives, Netcode for Entities will (simplified) discard the latest client prediction, rollback to the newest (server authoritative) snapshot state received from the server, and then re-predict (i.e. re-simulate) from that authoritative state.
Important note: IsFirstTimeFullyPredictingTick
will be true the first predicted tick they react to the jump input for (i.e. scenario [1] in this example), but IsFirstTimeFullyPredictingTick
will be false for [2] i.e. for every re-prediction of these older ticks.
Thus, we use IsFirstTimeFullyPredictingTick
to trigger jump V&SFX once. I.e. We use this API to prevent the sound and particle system from being triggered/re-started every single time we rollback & re-simulate. If we did not do this, weâd hear horrible distorted audio, and see like 10-30 overlapping particle systems, each triggered 1-2 ticks after the first.
However, importantly (and hopefully intuitively), we do not use IsFirstTimeFullyPredictingTick
to guard the jump itself, as that should be re-predicted every time we re-predict this ghost, exactly as the input denotes.
IsFirstTimeFullyPredictingTick
TL:DR:
- Do not use
IsFirstTimeFullyPredictingTick
for client predicted gameplay logic which needs to be re-simulated - like character controller movements (running, turning, jumping) and gameplay logic like weapon ROF cooldowns, ability timers, physics collision results, buffs and debuffs etc.
- Do use
IsFirstTimeFullyPredictingTick
for âone-shotâ client predictions like V&SFX, client predicted spawns (like bullets & projectiles) etc.
Further example: Imagine the player is hit by an enemy stun just before they jump, causing them to slide into the hole in the server authoritative simulation.
This cannot be predicted by the victim jumping player (as they donât have this stun information yet), so the victim human player will visually see themselves beginning to jump across the ledge. Theyâll hear the audio queue and see the particle system spawn.
They will be corrected by the server (most likely while theyâre still mid-air), and find themselves falling into the hole, with a âyouâve been hit by a stunâ sound FX triggering, and likely a HUD particle effect triggering on them.