So after trying pretty much everything to make my ball system be smooth, have client prediction while also keeping them in sync I’ve reached the point where im using a BodyPosition inside of an unanchored ball where I’m doing a basic gravity simulation and applying the position from that to the BodyPosition… this works OKAY I mean of course when the network owner has to change ownership theres of course hiccups but… I think I might have stumbled upon something here
Hear me out, let’s say that we have 5 clients in a game and the server spawns the ball then tells all the clients simultaneously to start their own simulations, keep in mind this simulation is deterministic and it’s just your basic gravity sim with position and velocity for the ball, alright so clients can also interact with the ball, to keep things simple lets just say only one client can hit it at a time
Since your simulation is completely deterministic and the only input that can change that is when a player hits the ball, let’s say one of the clients hits the ball… they are going to send the velocity of their simulation aswell as their timestamp using workspace:GetServerTimeNow() to the server
The server would then calculate the latency using the timestamp the client sent over, and let’s just call this local T_cs = workspace:GetServerTimeNow() - timestamp and then the server sends the current time then and also the same velocity they received from the client to all other clients
Then all the other clients will calculate the total round trip latency using the data sent over from the server
local T_sc = workspace:GetServerTimeNow() - data.timestamp
local T_total = data.clientToServerLatency + T_sc
And they would adjust the velocity in their simulation accordingly…
OH, and I almost forgot so a main problem could be desyncing but in this deterministic setup the only way it would deviate is there is some sort of high ping jump or maybe loss in packets but if it does happen some ways of combating is having all the clients send over their ball positions to the server and having basically a consensus and the outliers would have their simulations adjusted… this could happen maybe anywhere from 10 to 15 seconds, and of course when the clients do have to adjust it would be gradual so there isnt much hiccuping or warping or possibly speeding up their simulation could work too but I havent tried this
I know it’s possible that exploiters could send arbitrary values for the velocity and timestamp but is it probable? Most likely , so of course on the server you can just have sanity checks but I havent tested this yet but I have alot of faith it can work
Alright so I figured it out and it’s everything I couldve asked for!
Okay so, what I have done is I have created a simulation on the server and on the client which both run at a fixedTimeStep, in my case its 1/60, I make sure the simulation starts at pretty much exactly the same time, and both the client and server simulations use the same code to simulate. My simulation is completely deterministic so that means when its given the same inputs it’ll give the same outputs, the only thing that changes the state of the ball is when a client hits it.
For when a client does hit the ball I send over information for the server to reconstruct that that hit aswell as the timestamp using workspace:GetServerTimeNow(), when the server recieves it I do some lag compensation for the delay between the request, aswell as sending over the same data to all other clients and I also have them do lag compensation once it reaches them too!
I’ve done some testing on higher ping, lower ping, spamming the ball in succession and it works flawlessly, it’s not only smooth but its responsive on the client who hits it!
Once thing may be wondering is if multiple players hit the ball at the same time, and for my case this wont ever be able to happen in my game but, I did some testing with another player inside of a live server we hit it in succession in different directions and all of that and the balls got way out of sync but then only I kept hitting the ball and it took a few tries but the ball actually came back in sync like nothing ever happened it was really interesting to see, I guess the lag compensation really works wonders, but of course this is a pretty easy fix, just handle requests in a simple queue and process them one after another