Rigidbody drifts when user alt-tabs
Hello
When a Rigidbody is owned by a user who suddenly goes “inactive” (e.g. alt-tabs, loses focus, or exits), the other clients continue to see the object’s last known velocity and angular velocity. Those velocities remain “locked in” because there are no new updates coming from the owner to slow it down.
What is the most common design pattern to avoid this?
9 Replies
Hi @JimJamesJimJim. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
This is a common issue with networked physics in multiplayer games, especially when using Normcore's RealtimeTransform component with Rigidbodies. To address this problem, there are a few approaches you can consider:
1. Maintain Ownership While Sleeping:
The most straightforward solution is to use the "Maintain Ownership While Sleeping" option on the RealtimeTransform component. This prevents ownership from being cleared when the Rigidbody goes to sleep, which can help maintain consistent behavior even when a client becomes inactive.
As mentioned in the RealtimeTransform documentation:
"If you would like to avoid this behavior, use the inspector to switch the sleep option to 'Maintain Ownership While Sleeping.'"
2. Use Kinematic Rigidbodies:
For objects that should maintain their position when not actively controlled, consider making the Rigidbody kinematic when it's not being interacted with. This prevents physics simulation from continuing when the owner becomes inactive.
The RealtimeTransform documentation notes:
"When implementing logic like picking up an object, we recommend marking the rigidbody kinematic. While a rigidbody is kinematic, ownership will not be cleared automatically, and the default sleep settings can be used."
3. Implement a Timeout System:
You could implement a custom system that detects when an owner has been inactive for a certain period and then either transfers ownership to another active client or puts the object into a "frozen" state.
4. Use Server Authority:
For more critical gameplay elements, you might consider using Normcore Private's authoritative game servers to handle physics simulation. This can provide more consistent behavior across all clients, regardless of individual client states.
It's worth noting that the specific solution you choose may depend on your game's requirements and the behavior you want to achieve. The "Maintain Ownership While Sleeping" option is likely the simplest to implement and should address the immediate issue in many cases.
For more detailed information on networked physics in Normcore, you can refer to the Networked Physics guide.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------
<@351655082145611778> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@Normcore Assistant Give me an example pattern for allowing another remote user to take ownership of these realtime transforms to allow for a natural physics based settle. Rather than a freeze. Kinematic Rigidbodies are not an option as they must maintain believable physical interactions. Server authority is not a lane I'd like to persue currently
Let me check the knowledge base for you again. One moment! :books:
----------------------
To allow another remote user to take ownership of RealtimeTransforms and enable natural physics-based settling, we can implement a custom ownership transfer system. Here's an example pattern you could use:
1. Implement an inactivity detection system:
2. Create a custom component to manage ownership transfer:
3. Apply these components to your Rigidbody objects:
Attach both the
InactivityDetector
and OwnershipManager
components to each Rigidbody object that you want to participate in this ownership transfer system.
This pattern works as follows:
1. The InactivityDetector
monitors user input to determine if the local client is inactive.
2. The OwnershipManager
periodically checks if the local client owns the object and is inactive. If so, it clears ownership.
3. When ownership is cleared, other active clients can request ownership of the unowned object.
4. The first active client to request ownership will take control of the object and continue simulating its physics.
This approach allows for a natural physics-based settle because:
1. The object maintains its physical properties and interactions throughout the ownership transfer.
2. There's no "freezing" of the object; it continues to move and interact based on its last known velocity and the ongoing physics simulation.
3. The ownership transfer is seamless from the perspective of other clients, as the physics simulation continues uninterrupted.
Remember to adjust the inactivityThreshold
and ownershipCheckInterval
values to suit your specific needs.
This pattern aligns with Normcore's ownership model as described in the Ownership and Lifetime Flags documentation. It leverages the RequestOwnership()
and ClearOwnership()
methods of the RealtimeTransform component, which are part of the RealtimeTransform API.
Note that this approach may lead to brief periods where an object is unowned, which could potentially cause minor inconsistencies across clients. You might need to implement additional logic to handle edge cases or to ensure smooth transitions between owners.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@351655082145611778> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Is this in WebGL or Desktop
ideally you have Run In Background checked so they don’t stop sending updates if the window loses focus
This would still happen to me if someone is on quest for example and takes off the headset for a second, starts drifting away. Is it possibly due to the timeline interp / extrap failing and just constantly pushing it in the same direction?
we have extrapolation up to 250ms. In the Quest case the moment they take off their headset the Update() loop stops so we’re unable to serialize a model update to pause
desktop and web work differently though
continuing to extrapolate is probably fine for most cases though
maybe you could add custom timeout behavior or time limit