Setting rigidbody position with ".MovePosition()" a single time results in a desync between clients.
This successfully moves the rb to the desired position to the owner of the object but not the other clients.
7 Replies
Hi @gubebra. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
In NormalVR's networking solution, the synchronization of objects between clients is handled by the
RealtimeTransform
component. When you're dealing with a Rigidbody, RealtimeTransform
works a bit differently. Instead of synchronizing the localPosition
and localRotation
properties of the transform, it synchronizes the position
and rotation
properties of the Rigidbody, which are in world space instead of local space. This is because PhysX, the physics engine used by Unity, simulates all rigidbodies in world space (source (https://normcore.io/documentation/realtime/networked-physics#realtimetransform--physics)).
If you're trying to directly move an object, make sure to mark it kinematic. This lets PhysX know that you're controlling its position and it should not simulate the object directly. It also tells RealtimeTransform
that it should not clear ownership when the object goes to sleep (source (https://normcore.io/documentation/realtime/networked-physics#realtimetransform--physics)).
In a multiplayer environment, a game object and its transform can exist on multiple clients. This means that there are multiple copies that all claim to know the position of this object, but only one of them can be considered the source of truth. This is where ownership comes in. RealtimeTransform
treats the client that owns the object as the source of truth. All other clients follow along with the owner's copy of the transform or rigidbody (source (https://normcore.io/documentation/realtime/realtimetransform#how-it-works)).
Therefore, to move an object with a RealtimeTransform
component on it, you must be the owner of the RealtimeTransform
component. You can request ownership of a RealtimeTransform
component by calling RequestOwnership()
(source (https://normcore.io/documentation/realtime/realtimetransform#how-it-works)).
If you're calling RequestOwnership()
, setting the position of a transform, and then immediately calling ClearOwnership()
, nothing will happen because Normcore doesn’t send changes to the server immediately when you change ownership or the value on a model. Instead, it synchronizes at 20hz and sends the latest state. If you change something and then change it back immediately, nothing will be sent to the server (source (https://normcore.io/documentation/realtime/common-questions#im-calling-requestownership-setting-the-position-of-a-transform-and-then-immediately-calling-clearownershipbut-nothing-happens-how-can-i-fix-this)).
In summary, to ensure that the Rigidbody's position is synchronized across all clients, you need to:
1. Add a RealtimeTransform
component to the GameObject.
2. Request ownership of the RealtimeTransform
component.
3. Set the Rigidbody's position.
4. Avoid immediately clearing ownership after setting the position.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@599054560270483456> kapa.ai is still learning and improving, please let us know how it did by reacting below
I'm doing all 4 steps, and the ball was kinematic at the time I used move position.
maybe you are dropping the packet if it only moves once as RT uses unreliable
solution is to wiggle it a bit for a few frames or use reliable to send one message when moving once
or wait for normcore to add a reliable move message
Yeah that’s what I’m doing, although I don’t think this is the ideal solution
they are going to add reliable move in the future but this is the easy method now
the other method is to make your own RT with reliable move message
Thanks for the help Mechabit