Interested in practical experience here.
I’m starting with a base setup where the local and remote players are controlled with the same character controller logic, with movement input abstracted out into classes for local and remote.
Local player movement works off inputs from GetAxis which is transformed to work coordinates, Rotate to rotate the player, and manually adjusting Y axis for gravity.
One approach is to control the remote player just like a local player, which gives movement that looks just like the local player. Needs to be adjusted during play to correct for drift. In special cases such as jump landings, I’l need to ensure that I force the landing at the right spot, which will basically be the first server location that transitioned from not grounded to grounded.
The other approach is to always move the remote player towards the location given by the server. More accurate overall but needs a good amount of tweaking to make the movement look correct in comparison to the local player.
For special cases such as jumping, I’m going to always send an extra network update at the time of the action, so the remote clients always have an exact position to start the jump from (or whatever the special case is).
Currently I’m at the point where I have both versions of the above but not with all the tweaks and adjustments. Wanted to get some feedback before moving forward on that. I think either way could probably work, but very interested to hear anything I might have not thought of and avoid hitting an oh crap moment 10 hours into it.
Very interesting topic and something i have played around with a bit for our game. There are ofcause ups and downs for both approaches.
For number 1 you will always need to create a buffer so you have at least two input’s before you can execute it because you need the exact timing between the inputs to make sure you don’t get out of sync (like run straight for too long). Also the approach can be tough to use if you are working with fast-paced games and unreliable messages as losing one messages will fuck it up. Also extrapolation during delayed messages is also a problem with this approach.
For number 2 i personally also use buffers (but you dont need to) to make sure everything is smooth. I use same technic as Valve for their left 4 dead series but this means that everyone is a bit behind and you need to make things look correct locally, which is not easy depending on your game. Extrapolation is “easier” in this approach. As you mentioned then you can send extra packages at special cases. I do this for jump, double jump, wall jump and so on in our game.
Valve link: Source Multiplayer Networking - Valve Developer Community
I think most auth setup’s is sending input form client to server and location/rotation from server to clients.
Guess you could go with a mix of both where you use approach number two to correct players if problems occur with number one. But it is gonna be very difficult.
I think I’m leaning towards approach #2 as it will just have a lot fewer special cases that come up that I will have to account for, or that people abuse. The game is more of a massive combat mmo type game, and I don’t have most of the issues associated with FPS games and exact positioning relative to other players. Player/player collisions are disabled, targets can be acquired via aiming (using a huge hit box), but are then locked. Most abilities are aoe based.
Plus #2 will use less bandwidth, and in this game I have to optimize for large numbers of players in visual range.
Yeah it is easier to control bandwidth with approach #2. And i would more or less always take that approach myself 
The ‘slower’ the game is the easier is it to make everything look great and fair on clients. Does sound like its a good approach for you