Search Unity

Help Wanted - [MLAPI] NotServerException for Changing Ownership of XR Interactable

Discussion in 'Netcode for GameObjects' started by unity_7AFcA7XkjwO3Ug, Oct 5, 2021.

  1. unity_7AFcA7XkjwO3Ug

    unity_7AFcA7XkjwO3Ug

    Joined:
    Jul 26, 2018
    Posts:
    4
    Hello!

    I am working on a virtual reality multiplayer game and have run into an issue with MLAPI. The game centers around a ball spawned by and owned by the server that clients can grab onto and move around. I am trying to get the ball position to update and propagate across the server to other clients by changing the ownership of the ball to the player upon grabbing it. However, in my script attached to the ball, a NotServerException is thrown for
    GetComponent<NetworkObject>().ChangeOwnership(id);
    even despite this ChangeOwnership() method being called in a server RPC method with RequireOwnership set to false. How can I fix this?

    Thanks in advance!
     
  2. luke-unity

    luke-unity

    Joined:
    Sep 30, 2020
    Posts:
    306
    Can you share the code you are using? Is maybe your ServerRpc function on a MonoBehaviour instead of a NetworkBehaviour?
     
  3. unity_7AFcA7XkjwO3Ug

    unity_7AFcA7XkjwO3Ug

    Joined:
    Jul 26, 2018
    Posts:
    4
    Absolutely, here is my code for the script attached to the ball. The script right now inherits from XRGrabInteractable to get the methods that trigger upon grabbing the ball, so I don't think it can inherit from NetworkBehaviour as well. Could I try something like having the method in this script call another script that inherits from NetworkBehaviour to make the serverRPC method work? Thank you for your help!!

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.XR.Interaction.Toolkit;
    using MLAPI;
    using MLAPI.Messaging;

    public class BallGrabInteractable : XRGrabInteractable
    {
    //I've omitted some unnecessary code here

    [ServerRpc(RequireOwnership = false)]
    private void changeDiscOwnershipServerRpc(ulong id)
    {
    GetComponent<NetworkObject>().ChangeOwnership(id);
    }

    [ServerRpc(RequireOwnership = false)]
    private void resetDiscOwnershipServerRpc()
    {
    GetComponent<NetworkObject>().RemoveOwnership();
    }
    protected override void OnSelectEntered(XRBaseInteractor interactor)
    {
    ulong cID = 0;
    //Method to set cID to the player ID of the player who's grabbed the ball
    changeDiscOwnershipServerRpc(cID);
    base.OnSelectEntered(interactor);
    }

    protected override void OnSelectExited(XRBaseInteractor interactor)
    {
    resetDiscOwnershipServerRpc();
    base.OnSelectExited(interactor);
    }
    }
     
  4. unity_7AFcA7XkjwO3Ug

    unity_7AFcA7XkjwO3Ug

    Joined:
    Jul 26, 2018
    Posts:
    4
    Ah yes, it no longer gives the NotServerException when changing ownership now that I've moved it to a different script that inherits from NetworkBehaviour, but even still the position of the ball doesn't update on the server. The ball stays where it is even after the player throws it and the ownership is changed. Any ideas on how to fix this?
     
  5. amankAtUnity

    amankAtUnity

    Joined:
    Jan 27, 2019
    Posts:
    20
    Ping .. Any news on this?
     
  6. NoelStephens_Unity

    NoelStephens_Unity

    Unity Technologies

    Joined:
    Feb 12, 2022
    Posts:
    259
    Are you using MLAPI or NGO?
    If NGO, what version are you using?

    If you are throwing a ball, then generally speaking (with physics) you need to synchronize either your linear and angular velocities and/or force and torque depending upon how you are throwing the ball.

    The best way is to just use like a NetworkVariable<Vector3> for either force or velocity (you would end up having two) that has owner write permissions. Then, within the same NetworkBehaviour with the NetworkVariables, you would override OnOwnershipChanged and if the current owner is the same as the NetworkManager.LocalClientId you could just apply the most recent values of the two NetworkVariables to the now non-kinematic Rigidbody.

    I say it is the "best way" because NetworkVariables maintain state so in the event you have two players playing "catch" and a third player joins, then the third player, if given ownership, will already be up to date/synchronized with the linear and angular velocities. Also, because both NetworkTransform and NetworkVariables send delta updates every network tick you know that they should be "relatively" synchronized within the same frame.

    Speaking of network ticks, when changing ownership you might think about subscribing to NetworkManager.NetworkTickSystem.Tick and having some flag/bool that tells you if you need to change ownership so you can synchronize the changing of ownership with the network tick...while making sure to update your NetworkVariables at the same time you set the flag to change ownership. This assures that ownership, NetworkVariables, and NetworkTransform should all update within the same frame (on the new owner's side) together.

    If you just change ownership without synchronizing at least the linear and angular velocities, then the new owner's Rigidbody will do nothing (possibly just fall to the floor if gravity is applied).

    Let me know if this helps point you in the right direction?
     
    Last edited: Jan 27, 2024
  7. amankAtUnity

    amankAtUnity

    Joined:
    Jan 27, 2019
    Posts:
    20
    Hi,
    I really appreciate your fast support. In particular - since this is a widely discussed challange I am facing e.g.:
    - https://forum.unity.com/threads/move-other-players-with-xr-grab-interactable.1479960/
    - https://forum.unity.com/threads/xri-netcode-client-grab.1492559/
    - https://forum.unity.com/threads/how-to-change-ownership-on-interactables-in-netcode.1529314/
    - https://gamedev.stackexchange.com/questions/199174/unity-xr-toolkit-and-mirror-networking-grabbing

    I am using:
    - 2022.3.16f1
    - Netcode for GameObjects 1.7.1
    - Relay 1.0.5
    - XR Interaction Toolkit 2.5.2
    - 2 Meta Quest 3

    Following the SETUP mentioned here:
    -

    -


    GOAL: Each player is able to spawn objects that can be grabbed (XR Grabble) and moved arround by both players.

    PROBLEM: If client player grabs, moves or rotates the object, it snaps back to the old position after exiting select. I'm facing the problem even if i requestchange ownership via serverRPC. Reuqesting the ownership slightly changes the behavior - meaning that very small changes of rotations seam to be transmited to the sever somehow.

    ASSUMPTION: The missmbehavior ist somehow related to the fact that the grabbed object is reparented for interaction - but I am not sure.

    In the attachement you will find a screenshot of the object.In addition I attached the changeOwnership script.

    Does it make sense?
    Dod you need any additional information?
    Is there any sample showing how to have a xr grabbable object being moved arround by two players with netcode for GameObjects and Relay? I means this seamas to me a very obvious XR use case.

    Your help is very appreciated! Hope to hear from you soon!

    BR,
    Andreas
     

    Attached Files:

  8. amankAtUnity

    amankAtUnity

    Joined:
    Jan 27, 2019
    Posts:
    20