Search Unity

NetworkRigidbody - Is this supposed to work like this?

Discussion in 'Multiplayer' started by seon, Jan 25, 2008.

  1. seon

    seon

    Joined:
    Jan 10, 2007
    Posts:
    1,441
    I have a game scenario where 2+ players can drive around inside a game arena and push around rigidbody boxes (RBB's).

    All RBB's are Network.Instantiated from the server, and spawn correctly on the server and clients.

    Each RBB has a NetworkRigidbody script attatched to it and a networkView that is looking at the NetworkRigidbody script with Reliable Delta Compressed set.

    Each RBB also has a script that turns OFF the NetworkRigidbody script on the server version of RBB (based on networkView.isMine) and makes sure the NetworkRigidbody script is on on the client versions (clones).

    Everyone still with me?

    Ok, so this is the result...

    On the server, I can drive into the RBB's and they bounce around after impact and all clients reflect the movement and all is good!

    On ALL client machines, the cars drive into the RBB's and they can hardly even nudge the RBB's like the RBB's have a mass of 10000.

    This is consistent on ALL clients (Mac or PC), no matter who is the server.

    So...

    To me it looks like the networkView sync is going one way only, and that any updates on the server is reflected, but any updates on the clients are kinda not happening because the server version of the RBB hasn't moved and the clients are syncing with the server position/status.

    So to me it's looking like a one way synchronization.

    So, how am I supposed to setup a box with a collider and rigidbody in my scene to be able to be pushed around by any player at any time and have it updated correctly for all players?
     
  2. seon

    seon

    Joined:
    Jan 10, 2007
    Posts:
    1,441
    Anyone from UT around that can answer this please? So far, both Jon and I are stumped as to how this can be setup to work properly.
     
  3. Mr. Animator

    Mr. Animator

    Joined:
    Oct 2, 2005
    Posts:
    193
    This sounds like the behavior I would expect honestly - when it comes to networking, objects can really only be effected directly by the peer who 'owns' them. In this case, your server owns all of the rigidbodies, and the clients are only recieving information from the server regarding their transform information.

    In theory, your state-synchronized clients are moving around on the server the same way each client is controlling them locally. Therefore you might expect the server to then 'see' the clients' effect on your rigidbodies and then broadcast that effect to the clients. The reality though is that raw state synchronization won't really accurately reproduce the velocity of your client's characters. All you're getting is their position in space updated 15 times a second (or whatever you have your send rate set to). As such, the clients are merely popping forward in tiny increments, which may appear smooth, but will not produce accurate collision with rigidbodies, such as ramming a box as you've described.

    I think the results you're looking for will require some tricky business, such as fairly accurate prediction of your clients velocity (for accurate physics reactions).

    EDIT: On second thought, there's also the issue that while your client may ram a box locally, it won't really react because the server is constantly resetting the position of the box, since its the only authority on sending information about it...

    Here's an idea, perhaps you can have two rigidbodies... one that is the 'real' one, and one that is evaluated locally and doesn't render. Under normal circumstances, the local, invisible version is merely snapping to the server controlled 'master' version. However, on impact with one of the clients, the invisible one begins evaluating instead, and the client ignores the server's input for a half second or so. During this half second window, the client manipulates the box as it would normally, and after that brief window ends it sends an RPC to the server telling it where the box should now be and its current velocity/torque and so forth.

    Hopefully that made a little bit of sense. :)
     
  4. seon

    seon

    Joined:
    Jan 10, 2007
    Posts:
    1,441
    Ok, but if that is correct (as it looks to be) then how could you ever REALLY invent a game where to networked players can both effect the same object?

    There must be a method where the state can syncronised 2-way based on player interactivity on each local machine.

    Network updates are not fast enough to ensure that all the "client" colliders rigidbodies being tracked on the "server" player are accurate enough to reflect exactly what the client did... for example...

    My local car rams into a box on my local machine, and the clone of my car also rams into the box on the server machine, but due to lag and interpolation, on my machine where the box should have gone flying forward as I slammed sideways into it, the server machine (due to lag and int.) shoves the box half the distance and slightly the wrong way.

    So in this instance, though the box movement will be syncronised between all clients, the physical reaction I would expect to see based on my collision looks wrong.

    There must be a way for 2-way syncronisation.. UT?
     
  5. larus

    larus

    Unity Technologies

    Joined:
    Oct 12, 2007
    Posts:
    280
    If a car (client owned) crashes into a rigid body box (server owned). The cars movement is sent from client to server so the crash will happen on the server as well, just as if the car was actually locally controlled. The NetworkRidigBody script (from the networking example project), does synchronize position, velicoty, rotation and angular velocity with a 100 ms play back delay. I'll mention that again below but first ...

    If the server and client views of the world are exactly the same the client should interact with the box exactly as the server would. This is a sort of prediction as the client really isn't in control of the box in a world state sense only locally, he must bow to any network updates which control its position. He might hit the box causing some reaction, this reaction might not be identical on the server but the network updates should correct all errors. A script on the client side might apply network update the box in a controlled manner so the client side doesn't see the box skip around as errors are corrected. This is similar to what is done in the TPS-Auth scene in the networking example project.

    Are you setting isKinematic on the box by any chance on the clients? That changes the scenario as the client no longer sees the world exactly like the server. He sees the box as an unmovable obstacle and is reliant on getting updates on the box from the server, based on his local actions as played back on the server. Now the latency on the clients movement being played back on the server could be messing things up. So the client runs into the box and completely stops, the server sees the client just nudging the box as he was stopped immediately by the isKinematic property he is seeing locally. He doesn't see the car run into the box and continue going. This is especially bad when using the NetworkRigidBody script. The script is playing back the boxes movements with a 100 ms delay on the client, but it is "played back" in real time on the server.

    This is a bit tricky to understand and to solve efficiently (if it is the root of your problem). Its easiest to just not set isKinematic on the clients, keeping the clients view exactly like the servers view. Another solution is to play everything back with a 100 ms delay, including local changes, but that would make the local car seem unresponsive on the client side and pretty uncontrollable.
     
  6. seon

    seon

    Joined:
    Jan 10, 2007
    Posts:
    1,441
    Hi Larus,

    No, we are not using isKinematic anywhere. All clients see the same as the server and the difference in resulting hit between the client and the server is HUGE.

    The server car can push the boxes around like that are a mass of 5, and the client cars hit the boxes and hardly move them like they are a mass of 1000.

    The idea of the game is that players need to push their colour boxes onto the return bases the quickest. But right now all clients can hardly even move their boxes let along push them anywhere.

    I will send you a build offline with instructions to re-produce the issue.
     
  7. spawrks

    spawrks

    Joined:
    Nov 16, 2007
    Posts:
    89
    Seon,

    please post back what you find out. I am extremely curious about the ability of Unity to deliver physics networked play.
     
  8. seon

    seon

    Joined:
    Jan 10, 2007
    Posts:
    1,441
    Sure will... I am currently working with Larus off forum to get it all working and will post my results once I have them.
     
  9. Orion

    Orion

    Joined:
    Mar 31, 2008
    Posts:
    261
    Any news on this?
     
  10. seon

    seon

    Joined:
    Jan 10, 2007
    Posts:
    1,441
    Since starting this thread, I have not found any workable solution to this problem.

    The machine that OWNS the object in question (networkView.isMine) can interact with the object as you would expect with rigidbody physics reactions, but any other machine (client) that interacts with the object gets strange and useless results, definitely not you would expect from a rigid body interaction.

    i too am still waiting for a solution to this.
     
  11. ProtonOne

    ProtonOne

    Joined:
    Mar 8, 2008
    Posts:
    406
    I've only managed to get nice physics with with an authoritative server.

    I am going to be experimenting with the NetworkRigidbody script a bit, since my cars are acting crazy when they hit eachother.

    I think that turning off interpolation, by just setting m_InterpolationBackTime to 0, then replacing the following extrapolation line:
    Code (csharp):
    1. rigidbody.position = latest.pos + latest.velocity * extrapolationLength;
    With something that works within the physics system. Something like the physics character controllers on the wiki:
    http://www.unifycommunity.com/wiki/index.php?title=RigidbodyFPSWalker

    Haven't tried it yet, but this may help.
     
  12. shaun

    shaun

    Joined:
    Mar 23, 2007
    Posts:
    728
    Hi Seon,

    Networked Physics is not an easy one, and by the sound of things, you're hitting some similar problems we had a before. For us, each client takes responsibility for solving the physics simulation and the server runs the deterministic simulation that sends out a heartbeat to resync clients that get too off course. We thought that sending the same collision data to the clients, given the same simulation configuration would yield a predictable output, but PhysX appears to be non-deterministic, so that failed. Our heartbeat from the server holds things together - keeping the snapping to a minimum is a bit of work. Ideally we'd like to run the simulation separately from the visual output, so we can just interpolate the meshes toward their colliders - Tommy (touming) has worked a lot in this, I'm sure he'd be ok if you ask him a couple of questions - he may have a solution for two player controlled objects to affect a single rigidbody.

    Also, have you had a look at this article? I found it cleared up a lot of questions for me.
    http://www.gaffer.org/archives/gdc-slides-released#more-83
     
  13. Tubeliar

    Tubeliar

    Joined:
    May 21, 2009
    Posts:
    14
    I've tried a different approach that you might like. I've started toying around with the cars scene from the networking example, and wanted to add RBB's just to see if i could. In the cars example every player instantiates their own car, so they own and control it. But the network rigid body script makes sure that the car's clone on the server reacts like a rigid body too.

    I handle the boxes differently. Where the cars' authorities are distributed, the server has authority over all the boxes, so it instantiates all of them just like you do. Now the difference is that i don't use the rigid body interpolation script, but just the network transform interpolation one (used in the castle example i think). Additionally, i derived a different network initialization script on the box prefab.

    On the server the boxes are initialized just like the cars are, just the same as the original car init script. But on the client it destroys the collider and rigidbody components. This will turn them into 'dumb' boxes of course, but that is the idea. The server version still is a proper rigid body, and because of the transform synchronization, the dumb local version will move just as the server's real rigid body does! See, the local version doesn't need to be a rigid body, as long as it moves as if it were one :)

    So why destroy the collider? Because if we don't the server will keep resetting the box at the moment of impact because of latency, and the car will crash into it as if it were a brick wall - just like in your original problem! We can safely remove the local collider because the remote car is still a proper rigid body as is the remote box, so they'll collide as they should and the box' movement will be sent to the client by the transform updates.

    So why destory the rigid body component? Because now the box has no collider anymore, and if the rigid body component remains, it will keep trying to fall through the floor and everything else! You could of course disable the use of gravity, but as i said the local box doesn't need to be a real rigid body. Alternatively you could also keep the component around and try to use it for client side prediction.

    So there's my solution. A couple of peculiarities though... The authority is a bit strange, since it's distributed for the cars and server authoritative for the boxes. A side effect is that you'll see your car drive into (but really into, as in they'll occupy the same space) your cube until it responds after the latency time. It will respond okay, just a little late. On another note, in this way your boxes won't exert force on the client cars. You'll have to fake it by maybe changing the local collider into a trigger instead of deleting it, and adding a force on the car locally. And make sure the server car acts the same! On the plus side, you can drive boxes into other boxes and they'll react precisely as you'd expect :)
     
  14. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    Problem with your solution is that with higher latency you basically risk that the game becomes unplayable / jumpy on the client as the user input no longer has the control authority, its the server instead and if it has to correct things on a regular base the player experience suffers drastically

    Normally you would have both sides doing their job and only enforce corrections from the server if the data are outside of a given error threshold.
    I guess you didn't use the network time for your checks to ensure that "latency based error corrections" are not enforced on the client?
     
  15. Tubeliar

    Tubeliar

    Joined:
    May 21, 2009
    Posts:
    14
    Actually, in the cars example scene you will never become jumpy locally since you have authority over your own car. If you connection is bad, then you will appear jumpy on the server and all the other clients, and all the boxes will be jumpy to you. But yes, this could lead to strange things like your car showing up in an unexpected place after a delayed update finally arrives. But then again, any game will become choppy when you have high latency. It's unavoidable, isn't it? It's just a matter of how you deal with it.

    Both sides doing their job does sound like the best way, but as Shaun pointed out, the physics engine isn't deterministic. So you'll have to correct at least right after each and every collision.

    As for the rest, i'm not doing anything fancy here. This is just the simplest thing i could come up with that looks okay with up to a couple of players locally, so it seems to be an adequate solution to Seon's problem. Even if there's a lot of room for improvement like client side prediction. I don't know how it holds up in a real situation though. I've only toyed with Unity's network simulation, and that was still playable (although not very smooth) with the server at dial-up speed.
     
  16. Der Dude

    Der Dude

    Joined:
    Aug 7, 2006
    Posts:
    213
    Have you tried keeping all ownership on the server?

    If each client sends his input-information to the server and the server relays all positions back, then the physics-simulation will always be realistic and consistent.

    The problem then would be the lag between hitting the gas pedal and actually seeing the car move.
    This however can be more easily fixed by client-side prediction, than the RBB problem (I think), because the cars movement is relatively easy to predict, compared with the purely physics-driven movement of the RBBs.

    EDIT:

    I attatched a package containing a little test scene I was meaning to do for ages using the technique described above. Build the scene and test it!
     

    Attached Files:

  17. waronin3D_OLD

    waronin3D_OLD

    Joined:
    Jun 28, 2009
    Posts:
    4
    Hi, i had nearly the same problem and found a kind of conclusion for it.
    Tubeliars Idea wasnt to bad, but caused on my machine some problems
    like charakter run through boxes and stuff like that. So instead of deleting the collider i just scaled it.

    So this is my setup for a rigid body now:
    Use a simple Rigidbody with your prefrences.
    Add a Collider of your choise, i used BoxCollider.
    Use two NetworkViews, one for the RBB and one for the Transform. Both are Reliable Delta, didnt try Unreliable yet.
    And at least use the js below. It just changes your Setup for all clients.

    Code (csharp):
    1. var scale = Vector3(0.8,0.8,0.8);
    2.  
    3. function OnConnectedToServer() {
    4.     if (rigidbody)
    5.         rigidbody.useGravity = false;
    6.     if (GetComponent(BoxCollider))
    7.         GetComponent(BoxCollider).size = scale;
    8. }
    The negative thing about this is, that because of the two NetworkViews the traffic can become a little big if you have to many RBBs in your Scene.

    I also Post a sample package with a sample RBB Box.
     

    Attached Files:

  18. Zwakstroom

    Zwakstroom

    Joined:
    Jan 19, 2009
    Posts:
    27
    @Der Dude:
    I was browsing through this thread and saw your post, i was looking for something similar. I downloaded your package and tested it, but i can't find the added client-side predicition. You are sending input to the server and doing nothing locally on the client.

    Can you explain the predicition bit what you added? I would like to know :)

    Thanks in advance.
     
  19. GalZohar

    GalZohar

    Joined:
    Nov 28, 2012
    Posts:
    11
    The thread may be old, but I've been searching around a lot trying to avoid the exact same problem without having to write something that I will later have to completely re-write.

    I tried running a simple test where I network.instantiate a bouncing rigidbody ball on each client with an option to move your ball around, and at least when running locally it seems like they collide and synchronize just fine. Does this problem only occur when you have some actual latency that doesn't exist when running the game locally?

    I would seem like if you sync rigidbody velocities, then one update you will tell the server your position and velocity right before the position, and by your next update you would have already collided on the server, so the only difference between you and the server should be the non-determinism of the physics simulation and nothing else, regardless of latency, at least in such a situation where a moving client object is running into a server-owned zero-velocity RBB. Am I missing something here?

    Thanks for any help. I've spent 2-3 weeks so far searching for how to properly make a physics-based game work online with unity and no concrete answers found. Not even for something simple like some balls/boxes/capsules hitting each other in a rather simple way, not anywhere near those crazy physics examples where you have dozens of objects stacking up on top of each other.
     
  20. Ashkan_gc

    Ashkan_gc

    Joined:
    Aug 12, 2009
    Posts:
    1,124
  21. Quadgnim

    Quadgnim

    Joined:
    Sep 10, 2012
    Posts:
    132
    You need NetworkRigidBody attached on both the server and client. With networkView.observed set to the NRB on both sides. If you look at the code there is a read section and write section. The idea is to send velocity and angular velocity along with position and rotation. NRB does this.