The simplest way to explain client prediction
Multiplayer movement looks complicated. It is really three steps: predict, compare, correct.
Why you need it
Without server authority you cannot stop cheating. But if you send every input to the server and wait for an answer, the player sees a character that moves 80 ms after they press the key. That is unplayable.
The fix: the client applies the movement locally right away and sends the input to the server at the same time. In other words, it predicts the future.
Three steps
Predict: the client simulates the input immediately and writes the result into a history buffer keyed by tick number.
Compare: when the server sends its own result, the client compares it against what it stored for that tick.
Correct: if the difference is within tolerance, do nothing. If not, snap to the server position and replay every input received since that tick.
Traps in practice
The simulation must be deterministic. The same input from the same starting state must give the same result. A physics step driven by Time.deltaTime breaks this — use a fixed tick.
Do not correct abruptly. Smoothing small differences over a few frames stops the player from feeling teleported.
Where to start
First build single-player movement on a fixed tick and make it deterministic. Add the network layer afterwards.
Teams that reverse this order end up debugging movement bugs and synchronisation bugs at the same time. Speaking from experience.