private void OnDisable() { Grabbable grabbable = GetComponent <Grabbable>(); grabbable.OnAttached += OnAttached; grabbable.OnDetached += OnDetached; }
public void Store(Grabbable grabbable, CharacterVR characterVR = null) { grabbable.Rigidbody.isKinematic = true; grabbable.Transform.parent = transform; Vector3 attachPositionOffset = Vector3.zero; Quaternion attachRotationOffset = Quaternion.identity; grabbable.GetLocalAttachmentPositionAndRotation(transform, out attachPositionOffset, out attachRotationOffset, SlotType.name); grabbable.Transform.localPosition = -attachPositionOffset; grabbable.Transform.localRotation = Quaternion.Inverse(attachRotationOffset); if (!DataVR.Instance.grabbable.colliderEnabledWhenStored) { for (int i = 0; i < grabbable.Colliders.Length; i++) { grabbable.Colliders[i].enabled = false; } if (characterVR) { characterVR.RemoveNearInteractables(grabbable); //if fromInitialSpawn to avoid null reference remove on RemoveNearInteractables } } AttachedGrabbable = grabbable; AttachedGrabbable.SetOwnerSlot(this); }
public void Unstore() { for (int i = 0; i < AttachedGrabbable.Colliders.Length; i++) { AttachedGrabbable.Colliders[i].enabled = true; } AttachedGrabbable = null; }
public bool Unstore(Grabbable grabbable) { if (AttachedGrabbable != grabbable) { return(false); } Unstore(); return(true); }
private void OnTriggerEnter(Collider other) { Interactable i = other.GetComponentInParent <Interactable>(); if (i) { characterVR.AddNearInteractables(i); } Rigidbody rb = other.GetComponentInParent <Rigidbody>(); Grabbable g = null; if (i) { g = i.GetComponentInParent <Grabbable>(); } if (rb && (!g || !g.Attached)) { rb.collisionDetectionMode = /*CollisionDetectionMode.Continuous*/ CollisionDetectionMode.ContinuousSpeculative; //invalidates Rigidbody.Sleep(); in Grabbable Awake? } }
/// <summary> /// Detection of Interactables in a radius or inside a capsule. /// </summary> /// <returns></returns> private Interactable HoverInteractableDetection() { int length = DataVR.Instance.hand.hoverDetectionMaxColliders; //greater == more precision Collider[] results = new Collider[length]; float[] sqrDistances = new float[length]; Vector3[] closestPoints = new Vector3[length]; float hoverDetectionRadius = DataVR.Instance.hand.hoverDetectionRadius; if (DataVR.Instance.hand.hoverDetectionCapsule) { Physics.OverlapCapsuleNonAlloc(transform.position, transform.position + InteractableDetectionDirection.normalized * DataVR.Instance.hand.hoverDetectionCapsuleLength, hoverDetectionRadius, results, DataVR.Instance.hand.interactableElements, QueryTriggerInteraction.Ignore); } else { Physics.OverlapSphereNonAlloc(transform.position, hoverDetectionRadius, results, DataVR.Instance.hand.interactableElements, QueryTriggerInteraction.Ignore); } //#if UNITY_EDITOR // if(TrackedPoseDriver.poseSource == TrackedPoseDriver.TrackedPose.RightPose) // for (int i = 0; i < length; i++) // { // if(results[i] != null) Debug.Log("hoverResult: " + results[i], results[i].gameObject); // } //#endif //Order by distance for (int i = 0; i < length; i++) { if (results[i] == null) { sqrDistances[i] = float.MaxValue; continue; } //Get the closest point in the collider of the detected interactable to the hand Vector3 closestPoint = Physics.ClosestPoint(transform.position, results[i], results[i].transform.position, results[i].transform.rotation); //SquareDistance between this hand and closest point of the hover detected collider sqrDistances[i] = (closestPoint - transform.position).sqrMagnitude; closestPoints[i] = closestPoint; } //Sort results and closestPoints by distance float[] sqrDistancesCopy = new float[length]; System.Array.Copy(sqrDistances, sqrDistancesCopy, length); System.Array.Sort(sqrDistances, results); System.Array.Sort(sqrDistancesCopy, closestPoints); //Return first valid result for (int i = 0; i < results.Length; i++) { if (sqrDistances[i] == float.MaxValue) { return(null); } //3 types with different validation conditions to be detected //Interactable -> !AttachedGrabbable, sqrDistance < hoverDetectionRadius^2, visible || ethereal //Interactable Slot -> sqrDistance < hoverDetectionRadius^2, (slot.AttachedGrabbable && !AttachedGrabbable) || !slot.AttachedGrabbable && AttachedGrabbable && slot.SlotType == AttachedGrabbable.SlotType //Interactable Grabbable -> !AttachedGrabbable, visible || ethereal, !Stored //Grabbable before Slot because results[i].GetComponentInParent<Slot>(); can be truth with Grabbables (when they are stored) Grabbable grabbable = results[i].GetComponentInParent <Grabbable>(); if (grabbable) { if (!AttachedGrabbable && !grabbable.Undetectable && (grabbable.ConstrainedDetection ? sqrDistances[i] <= hoverDetectionRadius * hoverDetectionRadius : true) && !grabbable.Stored && (grabbable.Ethereal || results[i].transform.VisibleSpecificPointFrom(transform.position, closestPoints[i], DataVR.Instance.hand.blockingElements, QueryTriggerInteraction.Ignore))) { #if UNITY_EDITOR hoveredClosestPoint = closestPoints[i]; #endif return(grabbable); } continue; } Slot slot = results[i].GetComponentInParent <Slot>(); if (slot) { if ((slot.ConstrainedDetection ? sqrDistances[i] <= hoverDetectionRadius * hoverDetectionRadius : true) && ((slot.AttachedGrabbable && !AttachedGrabbable) || !slot.AttachedGrabbable && AttachedGrabbable && slot.SlotType == AttachedGrabbable.SlotType)) { #if UNITY_EDITOR hoveredClosestPoint = closestPoints[i]; #endif return(slot); } continue; } Interactable interactable = results[i].GetComponentInParent <Interactable>(); //It is useful to have things in interactable layer but without interactable component //Because they don't collide with CharacterVR layer if (interactable) { if (!AttachedGrabbable && !interactable.Undetectable && (interactable.ConstrainedDetection ? sqrDistances[i] <= hoverDetectionRadius * hoverDetectionRadius : true) && (interactable.Ethereal || results[i].transform.VisibleSpecificPointFrom(transform.position, closestPoints[i], DataVR.Instance.hand.blockingElements, QueryTriggerInteraction.Ignore))) { #if UNITY_EDITOR hoveredClosestPoint = closestPoints[i]; #endif return(interactable); } continue; } continue; } return(null); }