// Object Touch Auto Interact|Interactions|30120 namespace VRTK { using UnityEngine; using System.Collections.Generic; /// /// The Object Touch Auto Interact script allows grab or use interactions on an object to automatically happen upon touching the interactable object. /// [AddComponentMenu("VRTK/Scripts/Interactions/VRTK_ObjectTouchAutoInteract")] public class VRTK_ObjectTouchAutoInteract : MonoBehaviour { /// /// Situation when auto interaction can occur. /// /// Auto interaction can never occur on touch. /// Auto interaction will occur on touch even if the specified interaction button is not held down. /// Auto interaction will only occur on touch if the specified interaction button is held down. public enum AutoInteractions { Never, NoButtonHeld, ButtonHeld } [Header("Auto Grab")] [Tooltip("Determines when a grab on touch should occur.")] public AutoInteractions grabOnTouchWhen = AutoInteractions.Never; [Tooltip("After being ungrabbed, another auto grab on touch can only occur after this time.")] public float regrabDelay = 0.1f; [Tooltip("If this is checked then the grab on touch check will happen every frame and not only on the first touch of the object.")] public bool continuousGrabCheck = false; [Header("Auto Use")] [Tooltip("Determines when a use on touch should occur.")] public AutoInteractions useOnTouchWhen = AutoInteractions.Never; [Tooltip("After being unused, another auto use on touch can only occur after this time.")] public float reuseDelay = 0.1f; [Tooltip("If this is checked then the use on touch check will happen every frame and not only on the first touch of the object.")] public bool continuousUseCheck = false; [Header("Custom Settings")] [Tooltip("The interactable object that the auto interaction will occur on. If this is blank then the script must be on the same GameObject as the Interactable Object script.")] public VRTK_InteractableObject interactableObject; protected float regrabTimer; protected float reuseTimer; protected List touchers; protected virtual void OnEnable() { regrabTimer = 0f; reuseTimer = 0f; touchers = new List(); interactableObject = (interactableObject != null ? interactableObject : GetComponent()); if (interactableObject != null) { interactableObject.InteractableObjectTouched += InteractableObjectTouched; interactableObject.InteractableObjectUntouched += InteractableObjectUntouched; interactableObject.InteractableObjectUngrabbed += InteractableObjectUngrabbed; interactableObject.InteractableObjectUnused += InteractableObjectUnused; } } protected virtual void OnDisable() { if (interactableObject != null) { interactableObject.InteractableObjectTouched -= InteractableObjectTouched; interactableObject.InteractableObjectUntouched -= InteractableObjectUntouched; interactableObject.InteractableObjectUngrabbed -= InteractableObjectUngrabbed; interactableObject.InteractableObjectUnused -= InteractableObjectUnused; } } protected virtual void Update() { if (interactableObject != null && (continuousGrabCheck || continuousUseCheck)) { for (int i = 0; i < touchers.Count; i++) { if (continuousGrabCheck) { CheckGrab(touchers[i]); } if (continuousUseCheck) { CheckUse(touchers[i]); } } } } protected virtual void InteractableObjectTouched(object sender, InteractableObjectEventArgs e) { ManageTouchers(e.interactingObject, true); CheckGrab(e.interactingObject); CheckUse(e.interactingObject); } protected virtual void InteractableObjectUntouched(object sender, InteractableObjectEventArgs e) { ManageTouchers(e.interactingObject, false); } protected virtual void InteractableObjectUngrabbed(object sender, InteractableObjectEventArgs e) { regrabTimer = regrabDelay + Time.time; } protected virtual void InteractableObjectUnused(object sender, InteractableObjectEventArgs e) { reuseTimer = reuseDelay + Time.time; } protected virtual void ManageTouchers(GameObject interactingObject, bool add) { if (add && !touchers.Contains(interactingObject)) { touchers.Add(interactingObject); } else if (!add && touchers.Contains(interactingObject)) { touchers.Remove(interactingObject); } } protected virtual void CheckGrab(GameObject interactingObject) { if (grabOnTouchWhen != AutoInteractions.Never && regrabTimer < Time.time) { VRTK_InteractGrab interactGrabScript = interactingObject.GetComponent(); if (interactGrabScript != null && (grabOnTouchWhen == AutoInteractions.NoButtonHeld || (grabOnTouchWhen == AutoInteractions.ButtonHeld && interactGrabScript.IsGrabButtonPressed()))) { interactGrabScript.AttemptGrab(); } } } protected virtual void CheckUse(GameObject interactingObject) { if (useOnTouchWhen != AutoInteractions.Never && reuseTimer < Time.time) { VRTK_InteractUse interactUseScript = interactingObject.GetComponent(); if (interactUseScript != null && (useOnTouchWhen == AutoInteractions.NoButtonHeld || (useOnTouchWhen == AutoInteractions.ButtonHeld && interactUseScript.IsUseButtonPressed()))) { if (!interactableObject.holdButtonToUse && interactableObject.IsUsing()) { interactableObject.ForceStopInteracting(); } else { interactUseScript.AttemptUse(); } } } } } }