Delay from GhostInputSystemGroup to Prediction Loop when using Network Simulator

On the client side I experiencing an input delay when adding ICommandData within the GhostInputSystemGroup, so it does not get immediately processed in the Prediction Loop, but only when using the Network Simulator. This does not seem to happen without Network Simulator. It happens with small and big RTT Delays.

Simple example:
The player inputs the FireWeapon command on client side on the predicted server tick 357. The data is added to an ICommandData buffer using that tick within the GhostInputSystemGroup. But the followup systems which are running in the PredictedFixedStepSimulationSystemGroup within the same Player Loop Execution are only be processed till predicted server tick 356. This means that the user input is ignored in the current Player Loop Exeuction and considered at the next one.

While the additional lag is not really noticable for the player, it makes the input handling much more difficult, because the input is not handled and this has to be determined somehow in my case to adjust the next inputs. I would like that the input is always handled directly in the Prediction Loop, even with Network Simulator enabled. What are possible solutions to avoid this behavior?

Hey Faithless,

Unfortunately, this is by design.

The PredictedFixedStepSimulationSystemGroup only runs on “full ticks”. “Partial ticks” (e.g. frame 266 in my example above, note the 20% ```(int)(networkTime.ServerTickFraction * 100)


It's easier to reason about if you imagine that the Physics FixedStep tickrate is 1Hz (once per second). At this extreme, assuming 120Hz render rate, you would capture input 120 times before you could even "process" it.
*Which of those 120 inputs do you use? It's a game design decision ultimately.* 

See the doc for more details (although we should improve them to include these caveats): https://docs.unity3d.com/Packages/com.unity.netcode@1.0/manual/physics.html

Thus, because it's possible to have 2+ render frames for a single physics step, we must take the _**last**_ input to ensure the client predicted input is in sync with the actual simulation that will be performed on the server.

Note: This also occurs in singleplayer. E.g. If you put an ```Input.GetKeyDown``` inside a FixedUpdate, you are invisibly agreeing to a potential input latency. You'll even drop input (especially mouse input) unless you capture update in **Update**, then "accumulate" said input over render frames until it's actually needed.

This will therefore will also occur with the Network simulator disabled (you just need a high enough framerate, or a low enough Physics tick rate). See pic with my simulator disabled.
![9004096--1240696--upload_2023-5-10_11-1-15.png|971x153](upload://nXgpkEAmVMVsJtnOwdKXEgjXBIT.png)

Vs simulating high latency.
![9004096--1240690--upload_2023-5-10_10-53-46.png|975x118](upload://iIV70iE97K6LnMs2xsTcXnfpbN5.png)
_Note that "frame" here refers to: **UnityEngine.Time.frameCount**._
*My framerate is much higher when I have the Simulator disabled, so the problem is actually worse.*

Thanks for the explanation, Niki. I now understand the behavior and the reasons behind.

While a solution in general might be using the PredictedSimulationSystemGroup instead of the PredictedFixedStepSimulationSystemGroup, for physics based calculations, like in my case, it makes the things much more complicated. Another one would be splitting the predicting systems into these two groups, but that would tear the code, which is also not desirable.

But you also mentioned the full and partial ticks which can be queried using the NetworkTime singleton within the GhostInputSystemGroup. According to the kind of the tick, it can safely be determined whether the input will be processed directly in the following PredictedFixedStepSimulationSystemGroup of the same Player Loop Execution or not. In my case this allows to adjust the input handling appropriately, which fully solves my handling issue.

1 Like