xoros Yeah is more complicated... Ill try my best to describe how it works (as a developer i can write pretty complicated/convoluted code)
So to start out what I do is call functions simultaneously on all devices. I sync instructions not objects. Take a look at the Player event "Keyboard LeftArrow" You will notice i call two functions. One of them calls a function "MoveLeft" to move the player on my screen using a simulated action. You will notice the "MoveLeft" function takes a peerid as the parameter. This is so the function will for work any player (as you will see this is the same function each client will call as well using the the peerid they receive).
The other function I call "Sync_MoveLeft". This is where the magic happens. "Sync_MoveLeft" packages up the function name "MoveLeft" and a peerid (which is my id since im the one that called it and loads them to a dictionary and then sends the dictionary AsJSON to all peers. Each peer receives the JSON string and loads it back into a dictionary on their end. They read the function name they are supposed to call and the parameters (peerid) they should pass to it and call that same "MoveLeft" function for me on there screen. All clients call the same function. pretty neat...
But I found that the signalling just wasn't quite fast enough and the player would stutter a bit while moving. This where extrapolation comes in. What did was a create method for telling the peers to persist the function call on there end. You will notice in the Sync_MoveLeft function I also package up a persist value of 1. On the peers end they see this persist value and load the dictionary for constant use on their end. So every tick they will now call the move left command with the same peerid even if i don't send another. Poof! the player moves smoothly now.
But now the player will move left to infinity so I need a way to tell it to clear that persisted action. So in the "Sync_MoveLeft" I also package up a persist tag (action tag really) with a key name "move" and the peerid of the player (more than one player could be calling move left at the same time). So what each peer does is when the see a persist value of 1 they check the perstsTag and if a persistTag already exists is clears it. So MoveLeft is persisted until MoveRight is called or stop is called. Bingo.. solid movement and precision control. If i call the same function twice thats not big deal because the persits tag will match and just keep using the same function anyway.
Last just to account account for any potential lag I send a set position command every 30 ticks while I'm moving to ensure player objects don't drift to far out of sync while performing persisted actions.
And that in a nutshell is how it works. Theres a bit more in there but I think if you follow the code along with the comments it should make more sense over time. Its just nice to know that you can achieve smooth movement you just have to do some of the heavy lifting you self and write some extra code.