Repository navigation
NetworkRigidbody never syncs velocity, especially problematic for Distributed Authority #2903
Description
Activity
- addedstat:awaiting-triageStatus - Awaiting triage from the Netcode team.Status - Awaiting triage from the Netcode team.type:bugBug ReportBug Report
on Apr 28, 2024 In attempt to further mitigate problems with ownership change in rigidbodies, I tried making ownership changes occur purely by distance to closest player. This clearly shows how the velocity is lost as soon as ownership is transferred.
Unity_2024-04-28_20-09-08.mp4
The jitter is a result of the remaining linear and angular velocity on the client that originally pushed the object. They don't get cleared by the transfer.
Adding a
NetworkBehaviourthat synchronizes and applies linear and angular velocity helps mitigate the problem but ownership transfer is still subject to the lag that comes with the switch, arguably worse looking than on just touch.Unity_2024-04-28_20-15-26.mp4
Given the position is rolling back, I believe this is more of a NetworkTransform issue than a Rigidbody issue, though.
- addedstat:importStatus - Issue is going to be saved internallyStatus - Issue is going to be saved internallytype:feature-2.xNew NGO 2.0.0 feature, request or improvementNew NGO 2.0.0 feature, request or improvementand removedstat:awaiting-triageStatus - Awaiting triage from the Netcode team.Status - Awaiting triage from the Netcode team.
on Apr 29, 2024 - addedstat:importedStatus - Issue is tracked internally at UnityStatus - Issue is tracked internally at Unityand removedstat:importStatus - Issue is going to be saved internallyStatus - Issue is going to be saved internally
on Apr 29, 2024 Hello! Have you fixed it? I'm making a soccer game and can't sync the ball object in any way...
Hi, have you solved this problem by any chance, can you suggest a solution or some direction to look in?
- addedstat:reply-neededAwaiting reply from Unity accountAwaiting reply from Unity account
on Apr 1, 2025 We are planning on providing an update that will include the ability to automatically synchronize velocities, however until that becomes available there is an experimental Asteroids Project you can take a look at that will provide you with a reference on how this can be achieved.
The components of interest:
- BaseObjectMotionHandler
- Derives from
NetworkTransform(recommended for creating custom motion related components).
- Derives from
- PhysicsObjectMotion
- Derives from
BaseObjectMotionHandler
- Derives from
Within
PhysicsObjectMotion, you can find severalNetworkVariableproperties to handle synchronizing physics related values:- Mass
- AngularVelocity
- Velocity
- Torque
- Force
The two primary things you want to synchronize to keep the object moving in the same relative direction with the same rotations are the angular and linear velocity properties.
The next area of interest would be the OnAuthorityPushTransformState that is invoked whenever the authority of the
NetworkTransformhas detected enough change on the synchronized axis to push a state update out to all non-authority instances. The idea behind this is if you have any form of change happening on the authority side and the object in question is non-kinematic... for your particular use case it means that most likely either the linear (i.e. position) or angular (i.e. rotation) velocities have changed which makes this a perfect time to check both values and if they exceed a threshold value then update their respective NetworkVariable.So, at this point you have a
NetworkTransformandNetworkRigidbody(configured for "Use Rigidbody for Motion") where the authority is synchronizing all non-authority (i.e. kinematic) instances of the change in the Rigidbody's position and rotation (PhysX version) as well as the "current" linear and angular velocities.When ownership changes you just need to make sure the new owner applies the linear and angular velocities to the Rigidbody and since the new owner's instance will have changed from kinematic to non-kinematic the object should continue moving and rotating respective to the velocity values applied.
I would highly recommend updating to the most recent version of NGO (v2.3.0) as it also has some updates to the
BufferedLinearInterpolatorthat should help you with any fine tuning needed between the change in ownership.Let me know if this helps?
- BaseObjectMotionHandler
- addedstat:awaiting-responseAwaiting response from author. This label should be added manually.Awaiting response from author. This label should be added manually.and removedstat:reply-neededAwaiting reply from Unity accountAwaiting reply from Unity account
on Apr 11, 2025 I also had the same original issue as the OP -- trying to use Physics in a Distributed Authority Setting -- it is definitely bugged as the OP describes -- and in many other subtle ways that just synchronizing velocities does not fix (see bottom of my post for more info) ; I'm using Multiplayer Services (and NGO) 1.2.0, on Unity 6000.2.10f1
@NoelStephensUnity -- I tried to use your classes but uhh I ran into a plethora of issues, and I'm honestly quite frustrated...
Not all of these are issues, but in case it helps you figure out where I'm at, or anyone else following along in my footsteps, here's what I was dealing with:
1.) It looks like f01d4ed is already merged into main, so I copied the classes from the main branch...
2.) The classes heavily utilize other classes in the project, and it's all very tightly coupled, so I had to pull in a bunch of stuff, and do surgery on the code just to get it compiling.
3.) Physics Object Motion has an error in the Editor script:

Looks like a bug in BaseObjectMotionHandler, the original code was
baseObject.NetworkTransformPropertiesVisible = EditorGUILayout.BeginFoldoutHeaderGroup(baseObject.NetworkTransformPropertiesVisible, $"{nameof(NetworkTransform)} Properties"); if (baseObject.NetworkTransformPropertiesVisible) { base.OnInspectorGUI(); } else { serializedObject.ApplyModifiedProperties(); } EditorGUILayout.EndFoldoutHeaderGroup();I changed it to:
baseObject.NetworkTransformPropertiesVisible = EditorGUILayout.BeginFoldoutHeaderGroup(baseObject.NetworkTransformPropertiesVisible, $"{nameof(NetworkTransform)} Properties"); EditorGUILayout.EndFoldoutHeaderGroup(); if (baseObject.NetworkTransformPropertiesVisible) { base.OnInspectorGUI(); } else { serializedObject.ApplyModifiedProperties(); }4.) So... Network Rigidbody is still required... but we're augmenting it with duplicate functionality?

Which is one of my big complaints here... why are we writing our own pseudo-replacement for NetworkRigidBody, when that class already exists?? It seems kind of a "Path-of-Most-Resistance" approach to me. -- Why not just fix the bugs in NetworkRigidBody? -- It literally says that this is its job.
5.) There are weird hard coded limits that seem to be specific to the Asteroids game... (e.g. max mass == 5? and max velocity = 30?? -- and the editor will not let you go higher than that?), weird stuff regarding the pooling engine, damage values, and automatic velocity on first spawn is all coupled in there as well... -- (IMHO, those things really should be in separate game specific components... not tied into your networking system at such a low level...)
6.) Some of the messages were sending a timestamp as
Time.realtimeSinceStartup-- I changed those toNetworkManager.Singleton.ServerTime.TimeAsFloat7.) What I finally did get working of your classes was not helpful -- again though, I had to do so much surgery on it to even make it work in another project, who knows if it's correct or not.
Bottom line physics are glitchy as heck on Distributed Authority -- I believe this is a bug in NetworkRigidBody, not syncing things properly. -- It's much more than just syncing the velocity, though that is one major thing... it's also stuff like a stack of cubes all vibrating each other into the floor, or one player not being able to push a sphere that is owned by another player, etc.
- addedstat:reply-neededAwaiting reply from Unity accountAwaiting reply from Unity accountand removedstat:awaiting-responseAwaiting response from author. This label should be added manually.Awaiting response from author. This label should be added manually.
on Dec 3, 2025 Hi @BrainSlugs83,
(IMHO, those things really should be in separate game specific components... not tied into your networking system at such a low level...)
Those are experimental components that are indeed very specific to that version of the asteroids game and were more for reference purposes than to be used as a completed product. The asteroids game and associated scripts are not part of the NGO SDK (but built using the SDK).
It's much more than just syncing the velocity, though that is one major thing... it's also stuff like a stack of cubes all vibrating each other into the floor, or one player not being able to push a sphere that is owned by another player, etc.
A stack of cubes that are all owned by different clients?
With distributed authority, you have to determine your use cases and the expected outcome.
For things like "stacked boxes" you might keep those set to session owner permissions only as that assures that client is the "single source of truth" when it comes to physics for those bodies.
For things like not being able to push a sphere owned by another player, you can handle this a few ways...here are a few that come to mind:
Add a second collider to the thing "to push around" that is set as a trigger.
- Make the object transferrable.
- Make the tigger collider bigger than its actual collider so the trigger happens before a collision does.
- Upon a player entering the trigger you can transfer ownership immediately to that player, lock it for perhaps the current RTT (i.e.
NetworkManager.NetworkTimeSystem.TickLatencyis the average network tick latency between the service or server and the client in question. You can base your lock on the object off of that value to help reduce race conditions) with a multiplier to account for variations in latency and then have the owner unlock it.
Add a second Rigidbody as a child to the player prefab.
- Add a collider that projects in front of the player a bit.
- You can adjust this based on the latency between clients.
- The Ping Tool example shows you how to get this value.
- You can adjust this based on the latency between clients.
- Set the child GameObject to disabled by default.
- On non-authority instances, during spawn or post spawn, enable the child GameObject so it registers as a non-kinematic collider.
- Have script that projects the collider on the non-authoritative instance ahead of the player in the direction of the player's motion (you can calculate the velocity by taking the average delta in position over time. Here is some example NetworkAnimator code that obtains a calculated speed on non-authority instances).
- The child Rigidbody makes it such that non-authority player instances become kinematic while the child Rigidbody is non-kinematic.
Change your physics settings to handle all contact pairs. (not an optimal solution due to the expense)
- This includes kinematic to kinematic collisions.
- You have to handle the notification of the collision (can be tricky) or just apply an opposing force to non-kinematic bodies when they collide with kinematic bodies.
Synchronizing velocity can be useful if you could have a sudden change in ownership and would like another client to be able to "roughly" pick-up where the last owner left off, but it can also become expensive from a bandwidth and message processing perspective if you have a bunch of physics bodies spawned.
When you have a group of physics bodies that needs a single source of truth (i.e. stacked boxes) then you might get better results setting the prefab's NetworkObject to use session owner permission so physics is simulated for those instances only on the session owner...
Alternately, you could use an octree and divide space up into regions...
With an octree you could have players register as the "single source of truth" for a specific region until the player leaves (i.e. each leaf would define a cubic region of space) that space. Upon leaving it could re-distribute ownership between itself and the other clients since it would have authority over everything in the region that the client just left. It wouldn't be until the next player enters that region where the player's client would grab ownership for all spawned objects in that region.But... synchronizing velocities only allows you to persist the velocity upon ownership changing...but does not solve for the other side of things (collisions) which requires one of the possible solutions above.
Velocity can be calculated or synchronized...it depends upon what level of accuracy your project requires.
- addedstat:awaiting-responseAwaiting response from author. This label should be added manually.Awaiting response from author. This label should be added manually.and removedstat:reply-neededAwaiting reply from Unity accountAwaiting reply from Unity account
on Apr 8, 2026
Description
I witnessed bugged behavior when a rigidbody switches ownership in distributed authority, using the Transferrable flag without RequirePermission.
The symptom was such that once the object switched its authority from playerA to playerB, it would change how it moves.
This is because velocities (linear and angular) are not synced at all. I've confirmed as much in NGO 2.0.0-exp2's code.
All NetworkRigidbody/NetworkRigidbodyBase does is manipulate the interpolation and kinematic state, and registers itself onto the network transform.
The network transform has no awareness of the concept of neither linear nor angular velocities. It does not add any of them to its states.
Because of that, given even small amounts of lag, two objects can have wildly different opinions of how a non-kinematic rigidbody should be moving, and because of that, ownership cannot be easily transferred over.
Reproduce Steps
Though I have not used these exact steps, I have a simple project wherein I display the linear and angular velocities of a sphere being rolled by two players, the values show that despite the sphere rolling around when controlled by another player, its actual velocity values are zero'd out. See it here.
NetworkManagerand a way to host & joinNetworkRigidbody,NetworkTransform,NetworkObjectand set it to haveTransferrableas true.NetworkBehaviourthat would set the rigidbody's linear velocity to a non-zero value (such as Vector3.Forward) on authority alone, on spawn.Actual Outcome
Velocities are misaligned across clients, causing mismatch on ownership transfer.
Expected Outcome
Velocities are aligned and similar (identical) across all clients, allowing easy ownership transfer.
Screenshots
See the sample here, where
The editor client represents the red player, Witness that while the sphere is blue, it has no/almost no linear velocity, despite moving.
Environment
Additional Context
I don't see any easy way to solve this one without editing the
NetworkTransformclass such that its synchronized state includes linear and angular velocities. I recognize this is far from an ideal solution, though.There is no way to append new information to
NetworkTransformstate, nor is there any way to match its update rates, or interpolations.At best, right now I'm experimenting with making a network behavior that uses network variables to store linear and angular velocities, and on ownership change, if you became the owner, apply those. I don't think this is the best nor right solution, and it lacks the whole 'unreliable deltas' etc based details that
NetworkTransformsupports.Would love to know what's the proper way to go about solving this in the immediate, please!