AddForce on rigidbodies not syncing across network.

I have a network identity component along with a network transform component to sync rigidbody 3d attached to a gameobject (in this case a sphere). I have also added the object with the rigidbody to the list of spawnable prefabs on the networkmanager object/component. The rigidbody.AddForce is being called from a different gameobject networkbehaviour script this gameobject also has an attached network identity

When AddForce is called by the host/server, the force is added and the rigidbody updates on both the client and sever as expected.

When a client calls AddForce, it does not add any force on the server. On the client it appears to add the force for a short amount of time (on the client game only) before the object the force was added to reverts to its original position. However, running into the rigidbody with the client player does cause interactions between the colliders to reflect on both client and server, resulting in movement of the rigidbody on both. I have tried moving the AddForce calls to seperate [ClientRPC] and [Command] functions attached to a networkbehaviour inheriting script, which has no effect on the result of calling AddForce.

I’m sure I’m probably missing something obvious, but I can’t figure out how to get this part of networking to work. I appreciate any help that can be given.

exact SAME problem here :frowning:

You have to add the force in the command function (server side).
Can you provide some code ?

1 Like

(note this code is kind of weird due to trying to figure out what isn’t working)
In an OnTriggerEnter (attached to player object, inherits from network behaviour) I have:

  if (m_ball_network != null)
                {
                    if (m_networkIdentity.isServer)
                    {
                        Debug.Log("is server");
                        m_ball_network.RpcAddClientForce(ForceMode.Impulse, forceDir, forceMult);
                    }
                    else if (m_networkIdentity.isClient)
                    {
                        Debug.Log("is client");
                        m_ball_network.CmdAddForce(ForceMode.Impulse, forceDir, forceMult);
                    }
                    else
                    {
                        Debug.Log("not client nor server");
                        m_ball_network.CmdAddForce(ForceMode.Impulse, forceDir, forceMult);
                        //ball_RigidBody.AddForce(forceDir * forceMult, ForceMode.Impulse);
                    }
             
                }

These functions calls on m_ball_network (attached to the component with the rigidbody, inherits from networkbehaviour) are:

[Command]
    public void CmdAddForce(ForceMode forcemode, Vector3 forcevector, float multiplier)
    {
        Debug.Log("command add force");
        ball_rigidBody.AddForce(forcevector*multiplier, forcemode);
    }

    [ClientRpc]
    public void RpcAddClientForce(ForceMode forcemode, Vector3 forcevector, float multiplier)
    {
        Debug.Log("clientrpc add force");
        ball_rigidBody.AddForce(forcevector*multiplier, forcemode);
    }

Note that for both of the games that are running, upon hitting the ball they both log the “not client nor server” message (which is why that was changed to a command.) And I guess could be a part of the problem? I don’t know. I feel like i’ve tried everything I can think of.

Just tried moving the command to the same script that the OnTriggerEnter is in, and it has the same result as before.

Got a workaround for detecting isServer and isClient while running both instances on the same computer by combining the isClient, isServer checks with a hasAuthority check as well, and that part seems to work. Except that using the Debug.Log shows that neither the ClientRPC or Command functions are actually being called (once they were moved to the same script that on trigger is in). Using both functions does call the command in the separate m_ball_network script component… Now its too late for me to continue to get it working, so maybe tomorrow.

I do appreciate any help anyone can give me.

Do you have a NetworkTransform to sync the position of the ball ?
If yes: you don’t have to apply the force on the client. It will be applied by the server and replicated by the NetworkTransform
If no: the physics is not deterministic. you are not sure to have the same result.

It seems your gameobject is not spawned by the server. Cmd or Rpc wont be called properly.
How do you instantiate this object ?

2 Likes

Yes there is a network transform component attached to the gameobject, as well as a network identity component. I have tried all the sync options including syncing rigidbody3d, and transform.

The ball is a part of the multiplayer scene itself and as I understand it from the documentation NetworkServer.SpawnObjects is called to activate it on scene load. The prefab in the scene is also linked to the spawnable objects of the NetworkManager component in the network scene as well.

I believe I just got it working.

I believe the problem was that the script that does the Commands and Rpc to AddForce was not located directly on the base prefab of the player prefab that is identified as the player in the network manager.

The OnTriggerEnter function was in a script that was attached to a gameobject that was a part of the player prefab, but down in its hierarchy. Although this gameobject also had a networkidentity component attached, and the script inherited from network behaviour, it appears to be what was causing the issue. Using the OnTriggerEnter function on that gameobject, and within that function, having it call a CmdAddForce function that I added to a player networking script that also controls animation syncing on the base player prefab seems to have solved the issue.

Thank you for the help Neon. I appreciate it.

Edit: I would also like to note that this was experienced in version 5.1.0f3, which I had mistakenly assumed was the latest version because inside the editor the check for updates reported that it was the latest version. Figured this out when I ran into other problems involving multiple network components on the same game object, and clientrpc calls being invoked out of order, which was fixed in 5.1.2.

1 Like

Hi mate;
I just have the same problem. I have a networkbehaviour script attached to player prefabs checking the collisions and executing the addforce commands, also it edits the owner value of the ball script which is basicly i use for the positioning the ball and collided player. Player collides with ball and player scripts edits owner value of the ball and ball is positioning itself with that value. when player kicks the ball server player is doing all okay. client player has that odd behaviour which applies minimum force to ball.
how did you solve this issue?

I have the same problem :frowning:

mine just isn’t doing anything

When using physics with NGO there are some over-all differences than the typical single player model.

This all boils down to: Who has authority?

The authority controls the Rigidbody while the non-authority instances should (under normal conditions and if using NetworkRigidBody) have their Rigidbody set to kinematic mode. As such, a non-authority instance applying a force to to a Rigidbody will result in nothing happening (i.e. forces are not applied).
Generally speaking, you would use a NetworkTransform to synchronize any changes to the transform (authority side) based on the changes to the RigidBody (authority side). So, non-authoritative NetworkObjects with a Rigidbody (kinematic), NetworkRigidbody, and NetworkTransform will basically just “mirror” the transform changes happening on the authoritative side.

Ownership vs Authority:
Since the NetworkTransform is really what synchronizes the changes to the transform by the Rigidbody on the authority side, authority boils down to whether the NetworkTransform is configured to be server or owner/client authoritative. When server authoritative, ownership plays no role in the NetworkTransform authority as that is based on how the NetworkManager was started (i.e. server-host vs client). When owner authoritative, ownership becomes the key element to determine who:

  • Runs the physics simulation for the Rigidbody locally (i.e. non-kinematic)
  • Synchronizes the non-authoritative instances with the changes to the transform

By changing the ownership, the authority changes… but there is an issue… what about existing forces before ownership changed? How does one keep those synchronized?

Synchronizing Forces & Velocities:
My disclaimer here is that NGO is not designed to handle deterministic physics and the default Unity physics is not deterministic. However, you can achieve a reasonable physics model that does synchronize an object’s forces when ownership changes…and when you first start getting things “hooked up” it can be easy to overlook some concepts.
RPC/Custom Messages vs NetworkVariable
Always try to remember that an RPC or custom named message should be treated like an “event”. This means they are messages that will be received and processed only by the currently connected (and synchronized) clients. This also means that the parameters of those messages are considered “temporary values” that while they could be applied to local properties of the connected clients will not be synchronized with any late joining client. Both RPC and custom messages are transmitted on the same (at the end) frame they were invoked/sent.
NetworkVariables are considered “persistent state(s)” that both notify connected clients, that subscribe to the OnValueChanged notification, and synchronize late joining clients with the current state(s) during the connection process. Changes to NetworkVariables are sent on each new network tick. This makes the frequency in which NetworkVariables are updated tied to the NetworkManager.NetworkConfig.TickRate value (default is 30 times per second or every 0.033333ms)

So what does this all have to do with synchronizing forces?

Owner Authority Model And Collisions
You will find that the typical pattern is to handle collisions, on the authority side, with event message types since they are the fastest way to communicate that something has collided. However, if you think about “collisions” and ask “who has authority (on the Rigidbody)” you might not always need to communicate that something has collided. Of course, things get a bit more complicated when you start using an owner authoritative NetworkTransform as ownership changes and the Rigidbody changes (owner vs non-owner relative). You can then run into the conundrum of “Who reports a collision and who doesn’t”?
Triggers don’t play by the same rules as colliders since triggers are not dependent upon the Rigidbody being kinematic. As such, when using an “owner authoritative” approach you should consider designing your prefabs/objects with this in mind if you want to have owners of certain objects report a collision of other objects that are not owned. This type of scenario does require event notifications and a bit of “brain noodling time” to make sure that when a local object instance should ignore triggers (i.e. the local object is owned by the local client) or colliders (i.e. the local object is not owned by the local client). Be cautious here, as you can quickly get into race conditions if you are always trying to handle both trigger notifications and collision notifications…
As an example:
A missile that is configured for an owner authoritative model and belongs to a remote client (i.e. not the host or server) could most likely need to have the server detect “collisions” via triggers in order to send the “missile explode” event to all of the clients (if you wanted the server to be the “authority of missile impacts”).

The reason why I bring up collision handling is that often you want the collision of one body into another body to apply a force… but sometimes the two bodies aren’t both owned by the local client and so you need to determine “who has the ‘ultimate’ authority over a collision”? If you have an object-a owned by client-a and an object-b owned by client-b, who handles applying the force? This gets a bit complicated to explain, but the general idea here is you need to come up with a list of object types and the priority of collision handling (i.e. an enumerator property value or a tag applied to the GameObject) and then handle applying the resultant forces to both bodies. Of course, when you think about this scenario if you imagine the local object-a on client-a has “collision priority” then it would apply the force to its local object-a (which the result of this is synchronized every 0.03333ms via NetworkTransform) and then send an event (RPC or custom message) that targets the owner of object-b with some form of collision information.

So, that is applying forces… but synchronizing forces in the event ownership changes (the real reason to synchronize forces) can get slightly tricky and really depends upon what kind of force is being applied (i.e. its duration)… as it might only need you to synchronize the Rigidbody’s velocity and angular velocity values. This is where NetworkVariables can help you. You can subscribe to the NetworkManager.NetworkTickSystem.Tick in order to be notified when a new network tick takes place, and you can update your Rigidbody’s velocities and/or forces during this time…and “for the most part” every non-authoritative instance will be roughly (with an owner authoritative model) 1 network tick + half RTT (server to client relative) latent in getting updated.

Not to further confuse anyone, but you also need to consider “when is a good time to change authority” and “Is a TickRate of 30 going to be sufficient for your project’s needs”?

When using NetworkVariables with an owner authoritative model you need to make sure they are set with everyone read and owner write permissions… and depending upon your needs that might be the right configuration…of course you can consider client to server latencies and decide that updating the server, via an event message, with a Rigidbody’s velocities and/or forces yields a better result as the ownership change actually emits from the server-side… meaning the server could be updated (by the current owner) with more current Rigidbody forces & velocities if owners sent those updates via a ServerRpc and upon receiving that ServerRpc the server updates the object’s NetworkVariables…which then keep all clients up to date with the “most possible current” values.

Finally, there is always the very likely possibility that you will have the edge case scenarios where the server determines ownership should change in between ticks…which you could determine “what is an acceptable period of time to pass before the ownership changed message is propagated out?”. You can use the NetworkManager.NetworkTickSystem.Tick event to “tick synchronize” ownership changes which will assure the values updated are going to be as close as you can get.

But that won’t always make for a “smooth visual transition”… to spare you the extended version of why you most likely will want to separate “visual” from the “network synchronized” to achieve this… I went ahead and attached a project that gives you an example of how you can change ownership and keep the visuals of that change in ownership “looking right”. It is definitely an opinionated example, but the general foundation concepts are in place.


The semi-transparent purple ball is the NetworkObject and the checkered ball is the “visual representation” of that NetworkObject. The ball follows the owner client’s player, so in the image above you see the client (yellow and right side image) leads the host since the client has authority. When looking at the two images, the motion vector of the NetworkObject points from the left’ish bottom corner of the images to the top’ish right corner of the images. You should also note that the NetworkObject (semi-transparent purple) leads the visual for both the host and the client by about the same distance.

Hitting the space bar on the host side changes ownership between clients and rolls back to the host when it is owned by the last client connected.

Let me know if the information and attached example helps anyone?

9261783–1295883–OwnershipChangeOwnerAuthority.zip (23.7 KB)

2 Likes