- Home /
Networking - Best way to Sync Rigidbodies?
Hello,
I'm working on a type of pool/billiard game over a local network using Unity's builtin networking for iOS. I'm trying to figure out the best way to sync position of the balls.
Basically, I want it so when it's Player One's turn, that device only applies the actual velocity to the balls when hit, and then syncs the outcome of the position to the client / Player Two. And the same for when its Player Two's turn. So who's ever turn it is, will essentially control the balls physics, and sync it to the client.
What I've done so far is this, which is attached to all the balls (FYI, the initial force applied to the balls are also called locally, and synced in the same manor):
function Update(){
if(GC.NETWORK.myTurn){
networkView.RPC("SyncVelocity", RPCMode.Others, rigidbody.velocity.x,
rigidbody.velocity.y,
rigidbody.velocity.z);
}
}
@RPC
function SyncVelocity(x : float, y : float, z : float){
rigidbody.velocity.x = x;
rigidbody.velocity.y = y;
rigidbody.velocity.z = z;
}
Note how I'm only sending that RPC to 'others' .... so the player that ISNT playing. Is this the correct way to do it? I'm worried that because I'm sending this every frame it might 'overload' the clients network listener ... if thats even a thing?
I had also synced the local position and rigidbody velocity before, but when testing on my iPad2, and being the player who ISNT playing, everything went laggy, suggesting that there was too much data being sent from the current players RPC? (Although I didnt get lag when on my iPhone5 as being the 'none player'. Maybe because its just generally better at processing it all).
I don't know, just need a point in the right direction really?!
Thanks.
You don't need to do it every frame, you should use an InvokeRepeating. Also, it looks like every ball is sending an RPC every frame? You can store moving balls in a list and do them all at once. Also, you can send a Vector3 in an RPC.
If one player is controlling the physics, though, why not just disable the rigidbodies during the other player's turn and send xy position-at-time updates?
Answer by Pangamini · Dec 09, 2013 at 12:48 PM
You are making a turn-based game, which makes things a lot easier for you. Floating point operations may give different results on different platforms, so expecting that same setup will have same results is ingenuous. And proper realtime networking of physics is a very complex problem, usually combining prediction (what you do, local physics calculation) and corrections based on data from server.
But as i said, you don't need to deal with this since your game is turn based. So why not just record the ball movement in frames (on the server), send it (and wait for the client to receive the whole "movie")) and then, after all data is transmitted, simply replay the motion? No need for real-time simultaneous ball motion on all PCs, unless you want to be able to shoot them.
Having all physics being calculated on server will simplify the coding and prevent cheating.
Okay, so with this 'movie record' system, will I be expecting lag? Because I preferably want it to be almost instant sync, as its a local game - players will be sitting/standing next to one another, so lag will not work in this particular project.
Also, player one is always the server. Its not one of those games where there is a server that is a NPC, and players connect as clients (excuse my lack of ter$$anonymous$$ology).
So, if your 'movie clip' system doesn't have lag, how would I go about doing it? Thanks
You could run the physics at 10x speed or faster, tracking only the time and place of each collision for each ball, then both players would effectively be watching a replay and the clients' replay would only be delayed by a second or so. I think most existing pool sims already do something like that- if you made one with 2-way real-time physics sync, yours would be the first. And it wouldn't be a good thing in this case.
That's exactly what i would do, but not just 10x faster, but simply - as fast as possible (in single frame or separate thread) but in unity that might mean you'd need to implement some other physics engine? I don't think you can unhook the current one from the realtime simulation.
Or, an acceptable solution would be to stream this "movie" while it's still being generated on the server. With some little latency. And if they sit on a LAN, you don't need to worry about amount of data (much). Then add some simple interpolation between those keyframes too, possibly creating non-regular additional keyframes on ball collision (so the interpolation reaches the exact point)
Okay, so in terms of actual coding, how would I build the recording? So - every 20 frames, send the record over and essentially 'play' it with a lerp? Also - will I need to turn off the rigidbody/collisions on the player thats viewing the recording?
Answer by Jamora · Dec 10, 2013 at 02:40 PM
I would have the server NetworkInstantiate all the balls, so that it is the owner. Have the NetworkView of each ball observe its Transform (it is by default) and set the transfer mode to unreliable.
Now, playing as the server is simple, as all computation is done locally and merely transmitted to the other players. But, how to allow the remote player to actually play? Easy enough: have each remote player send the parameters of each original strike to the cueball to the server. Then the server performs this strike and transfers all positions over the network.
This method will need to be improved if you have a fancy 3D pool-game where you actually hit balls with sticks and allow the physics to handle the rest (mainly because of the lag between hitting the ball and it actually starting to move can be discernable). But for a 2D, top-down view the only things you need to transfer over the network from clients to the server are
the angle at which the cueball was hit (direction)
the power of the hit (speed)
possibly which part of the ball was hit (for curve-balls)
In one sentence: Only send the parameters of the strike to the cueball to the server, and forget about controlling balls remotely.
The main problem here is that floats can have different results on different CPUs. Even if those are tiny differences, in physics simulation they will accumulate.
Because only the parameters of the strike (not the actual hit) are sent to the server, only one computer is doing the physics simulation; the server. The server constantly syncs the positions of the clients balls to its own to achieve the illusion of the remote player actually playing.
The remote client is doing three things:
displaying the table
receiving position information from the server for each ball
occasionally sending out data on how the cue ball should be hit (but doesn't actually hit it)
Your answer
Follow this Question
Related Questions
why my cmd function not work? 1 Answer
Joining a Running Server (Game) and Waiting for Game State Data. How? 1 Answer
IL2CPP - RPC doesn't work 1 Answer
Send RPC in 2 scene 0 Answers
RPC calls client to server Errors 1 Answer