dontworry
dontworry2mo ago

How can I ensure only 1 player at a time can hold an item with xr interaction toolkit?

I'm using RequestOwnership and ClearOwnership so any player can grab an item with Realtime Transform and move it around networked. But with the XR Grab Interactable component it allows another player to grab the item when it's already being held, and then it desyncs and each client sees themself holding the item. I'm using the XR Grab Interactable's Interactable Events (Select and Select Exited) to call methods with RequestOwnership.
7 Replies
kapa.ai
kapa.ai2mo ago
Hi @dontworry. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To ensure that only one player at a time can hold an item in a networked environment using the XR Grab Interactable component, you need to manage the ownership of the RealtimeTransform component associated with the item. When a player grabs an item, you should call RequestOwnership() on the RealtimeTransform component. This will make the player the owner of the object, and their updates to the object will be visible to other clients. Other clients can then use the ownerID property on RealtimeTransform to see who is holding the item.
realtimeTransform.RequestOwnership();
realtimeTransform.RequestOwnership();
However, you should be aware that 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. In this case, you should skip calling ClearOwnership(). As long as the RealtimeView’s owner is None, then any other client in the future can just call RequestOwnership() to take over the transform and move it.
// Don't do this
realtimeTransform.RequestOwnership();
// Change the position of the transform
realtimeTransform.ClearOwnership();
// Don't do this
realtimeTransform.RequestOwnership();
// Change the position of the transform
realtimeTransform.ClearOwnership();
Instead, you should only call ClearOwnership() when the player releases the item. This will allow other players to grab the item.
// When the player releases the item
realtimeTransform.ClearOwnership();
// When the player releases the item
realtimeTransform.ClearOwnership();
Remember that a RequestOwnership() call is only rejected if the RealtimeView or a parent RealtimeView is owned by a different client. So, if a player tries to grab an item that is already owned by another player, the RequestOwnership() call will be rejected, and the item will remain in the possession of the current owner. Sources: - How can I check who is holding an object? (https://normcore.io/documentation/room/common-questions#how-can-i-check-who-is-holding-an-object) - I’m calling RequestOwnership(), setting the position of a transform, and then immediately calling ClearOwnership()—but nothing happens. How can I fix this? (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) - How it works (https://normcore.io/documentation/realtime/realtimetransform#how-it-works) - Ownership (https://normcore.io/documentation/realtime/realtimeview#ownership) ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@666359106176679966> kapa.ai is still learning and improving, please let us know how it did by reacting below
dontworry
dontworry2mo ago
When a player grabs an item I'm calling RequestOwnership, and when another player grabs the same item that is already being held, it may be rejecting this new RequestOwnership call since it hasn't been released yet by the first player and ClearOwnership hasn't happened. But the problem is XR Grab Interactable still allows the 2nd player to grab the item and see themself locally moving it around, even if it's owned by the 1st player still. When the 2nd player releases the item it snaps back to the 1st player's hand since they are the owner and still holding it on their client.
Mechabit
Mechabit2mo ago
a simple solution is to set the rigidbody to kinematic and do a check for isKinematic before grabbing the item another option is to check if the owner ID is -1 (unowned) before grabbing another option is to create a custom model with a bool called canGrab which you flip to false when someone picks it up
dontworry
dontworry2mo ago
thanks for the help. i've started attempts for options 2 & 3, but how do you suggest I interrupt "before grabbing"? i was changing the Interaction Layer Masks on the XR Grab Interactable to "OneHolder" and the XR Origin Rig to "OneHolder" so the other player's Rig that is still set on "Default" wouldn't be able to grab, in theory... but I can't figure out how to detect which player did the "Select" grab on the XR Grab Interactable, since the corresponding XR Direct Interactor components are on the XR Origin Rig (only 1 in the scene), not on the avatar prefabs that get called in as separate ids in the scene.
Mechabit
Mechabit2mo ago
just disable the interactable for other players while it's being held
dontworry
dontworry2mo ago
that is much easier 🙂 i couldn't understand how to determine "other players" in the update sync then i realized isOwnedRemotelySelf does the trick! thanks @Mechabit 🙏