cancel
Showing results for 
Search instead for 
Did you mean: 

Switching Interactions on Networked Grabbable Objects

vrprojS7
Honored Guest

In the colocation multiplayer ar app I am building for Meta Quest 3, I am using Meta XR SDK and Photon Fusion for networking. I have set up a prefab for instantiation across the network. the prefab itself contains multiple children which carry NetworkObject components thmeselves, because these objects are replicas of the NetworkedGrabbableObject building block. Their hierarchy is as follows.                        hierarchy.jpg

the Pillar_01_Module are the visuals and therefore not important. The GrabInteraction is basically the child that an object gets after we add Grab Interaction, via right click -> Interaction sdk -> add grab interaction. the RotateInteraction child is the same except for the additional component of OneGrabRotateTransformer, which is passed into the One Grab Transformer optinal parameter of the object's Grabbable component. the Inspectors of the BaseGrabbable, GrabInteraction and RotateInteraction with that order are:
BaseGrabbableInspector.jpgGrabInteractionInspector.jpgRotateInteractionInspector.jpg

The logic i want to achieve is: players can move the BaseGrabbable, being able to take it from each other's hand (works just fine). The BaseGrabbable's trigger BoxCollider collides with the Base's trigger BoxCollider. OnTriggerEnter is called (i have checked that it gets called on all player's successfully, since the two colliders collide in all players, therefore, i am sure no rpc is needed for this logic). OnTriggerEnter snaps the BaseGrabbable object to the position of the Base object, disables itsGrabInteraction child and enables its RotateInteraction child. At this point, all the users should be able to simply rotate the BaseGrabbable, while it remains in a fixed position, while all the other users should be able to see it rotating. However, only the user that was controlling the BaseGrabbable when OnTiggerEnter was called is able to rotate it (the rotation is visible to the other ofcourse but the other cannot interact with it).

I have checked whether the GrabInteraction applies changes to the BaseGrabbable BoxCollider or RigidBody, making it non interactible, until the controlling user leaves it be. I was wondering if these changes persist since the user never releases it, but the GrabInteraction is simply deactivated. But if ound nothing there and I don't think that was the case. I then checked whether i should manually ReleaseStateAuthority of the network object when disabling the GrabInteraction and enaling the RotateInteraction, in order for other players to be able to interact with it, but TransferStateAuthority components allow user's to take state authority from others so that was not the case either.
Here is my PillarPart script, which is carried by the Base object (not the BaseGrabbable)

public enum PillarPartState
{
    None,
    Positioned,
    Rotated,
    Smoothed
}

public class PillarPartLogic : MonoBehaviour
{
    private GameObject nextPart;
    private GameObject currentGrabbable;
    public  PillarPartState partState;
    private BoxCollider triggerCollider;
    private int smoothCounter;

    private void Awake()
    {
        triggerCollider = GetComponent<BoxCollider>();

        if (this.name == "Base")
        {
            nextPart = transform.parent.Find("Part1").gameObject;
        }
        else if (this.name == "Part1")
        {
            nextPart = transform.parent.Find("Part2").gameObject;
        }
        else if (this.name == "Part2")
        {
            nextPart = transform.parent.Find("Part3").gameObject;
        }
        else if (this.name == "Part3")
        {
            nextPart = transform.parent.Find("Part4").gameObject;
        }
        else if (this.name == "Part4")
        {
            nextPart = transform.parent.Find("Part5").gameObject;
        }
        else if (this.name == "Part5")
        {
            nextPart = transform.parent.Find("Part6").gameObject;
        }
        else if (this.name == "Part6")
        {
            nextPart = null;
        }

        currentGrabbable = transform.root.Find(this.name + "Grabbable").gameObject;
        // TODO: highlight currentGrabbable
    }

    private void Start()
    {
        partState = PillarPartState.None;
        smoothCounter = 0;
    }

    private void OnTriggerEnter(Collider other)
    {
        if (partState == PillarPartState.None && other.name == this.name + "Grabbable")
        {
            Debug.Log($"{this.name} collided with {other.name}");
            GameObject grabbableGrabInterraction = other.transform.Find("GrabInteraction").gameObject;
            GameObject grabbableRotateInterraction = other.transform.Find("RotateInteraction").gameObject;

            // disable grab interraction. object is now non interractible
            grabbableGrabInterraction.SetActive(false);

            // snap at position and rotation
            other.transform.position = transform.position + new Vector3(0.0f, 0.04f, 0.0f);
            Vector3 eulerAngles = transform.eulerAngles;
            other.transform.eulerAngles = new Vector3(eulerAngles.x, other.transform.eulerAngles.y, eulerAngles.z);

            // enable rotate interraction. players can now only rotate the object around the y axis
            grabbableRotateInterraction.SetActive(true);
            partState = PillarPartState.Positioned;
        }
        else if (partState == PillarPartState.Rotated &&
            (other.name == "LeftHandAndControllerTrigger" || other.name == "RightHandAndControllerTrigger"))
        {
            smoothCounter++;
            if (smoothCounter == 3)
            {
                // activate smoothed visuals, deactivate rough visuals
                transform.Find("SmoothVisuals").gameObject.SetActive(true);
                transform.Find("RoughVisuals").gameObject.SetActive(false);
                partState = PillarPartState.Smoothed;

                // deactivate trigger collider
                triggerCollider.enabled = false;

                // increment completed parts in parent PillarBuilding component
                transform.root.GetComponent<PillarBuilding>().partsCompleted++;
            }
        }
    }

    private void Update()
    {
        if (partState != PillarPartState.Positioned || !currentGrabbable)
            return;

        if (Mathf.Abs(currentGrabbable.transform.eulerAngles.y - transform.eulerAngles.y) < 5)
        {
            GameObject grabbableRotateInterraction = currentGrabbable.transform.Find("RotateInteraction").gameObject;

            // disable rotate inerraction. object is now non interractible
            grabbableRotateInterraction.SetActive(false);

            // snap at position
            currentGrabbable.transform.position = transform.position;

            // activate rough visuals
            transform.Find("RoughVisuals").gameObject.SetActive(true);

            // enable the next part for collision detection
            if (nextPart != null)
                nextPart.SetActive(true);

            // delete controlled object
            Destroy(currentGrabbable);
            currentGrabbable = null;

            // if this was the last part to be placed, enable smoothing logic
            if (this.name == "Part6")
            {
                transform.root.GetComponent<PillarBuilding>().EnablePillarSmoothingLogic();
            }
        }
    }
}

 

 


Can anyone provide some insight?

0 REPLIES 0