using UnityEngine; using UnityEngine.XR; using UnityEngine.XR.Interaction.Toolkit; public enum HandInteractionRestriction { None, Left, Right } public class XRGrabOffsetInteractable : XRGrabInteractable { [SerializeField] private HandInteractionRestriction handInteractionRestriction = HandInteractionRestriction.None; [SerializeField] private bool allowOnlyOneHand = false; private Vector3 initAttachLocalPosition; private Quaternion initAttachLocalRotation; void Start() { if (!attachTransform) { GameObject grab = new GameObject("Grab Pivot"); grab.transform.SetParent(transform, false); attachTransform = grab.transform; } initAttachLocalPosition = attachTransform.localPosition; initAttachLocalRotation = attachTransform.localRotation; } protected override void OnSelectEntered(SelectEnterEventArgs args) { var interactor = args.interactor; if (interactor is XRDirectInteractor) { attachTransform.position = interactor.transform.position; attachTransform.rotation = interactor.transform.rotation; } else { attachTransform.position = initAttachLocalPosition; attachTransform.rotation = initAttachLocalRotation; } if (allowOnlyOneHand) { if (interactor.GetComponent<XRController>().controllerNode == XRNode.LeftHand) handInteractionRestriction = HandInteractionRestriction.Left; else if (interactor.GetComponent<XRController>().controllerNode == XRNode.RightHand) handInteractionRestriction = HandInteractionRestriction.Right; } base.OnSelectEntered(args); } protected override void OnSelectExited(SelectExitEventArgs args) { if (allowOnlyOneHand) handInteractionRestriction = HandInteractionRestriction.None; base.OnSelectExited(args); } public override bool IsHoverableBy(XRBaseInteractor interactor) { if (handInteractionRestriction != HandInteractionRestriction.None) { if ((handInteractionRestriction == HandInteractionRestriction.Left) && (interactor.GetComponent<XRController>().controllerNode != XRNode.LeftHand)) return false; if ((handInteractionRestriction == HandInteractionRestriction.Right) && (interactor.GetComponent<XRController>().controllerNode != XRNode.RightHand)) return false; } return base.IsHoverableBy(interactor); } public override bool IsSelectableBy(XRBaseInteractor interactor) { if (handInteractionRestriction != HandInteractionRestriction.None) { if ((handInteractionRestriction == HandInteractionRestriction.Left) && (interactor.GetComponent<XRController>().controllerNode != XRNode.LeftHand)) return false; if ((handInteractionRestriction == HandInteractionRestriction.Right) && (interactor.GetComponent<XRController>().controllerNode != XRNode.RightHand)) return false; } return base.IsSelectableBy(interactor); } #if UNITY_EDITOR private void OnValidate() { if (allowOnlyOneHand) handInteractionRestriction = HandInteractionRestriction.None; } #endif }