123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- /// <summary>
- /// Checks for trigger colliders with IXRHoverable components added, and lets user click or grab them if they
- /// have IXRClickable or IXRGrabbable scripts on them.
- /// </summary>
- [RequireComponent(typeof(Collider))]
- public class ZEDXRGrabber : MonoBehaviour
- {
- public ZEDControllerTracker_DemoInputs zedController;
- private IXRHoverable hoveringObject;
- private IXRGrabbable grabbingObject;
- private bool isGrabbing
- {
- get
- {
- return grabbingObject != null;
- }
- }
- private List<IXRHoverable> collidingHoverables = new List<IXRHoverable>();
- private List<IXRClickable> collidingClickables = new List<IXRClickable>();
- private List<IXRGrabbable> collidingGrabbables = new List<IXRGrabbable>();
- [Space(5)]
- [Header("Sounds")]
- public AudioClip clickSound;
- public AudioClip grabStartSound;
- public AudioClip grabEndSound;
- public AudioClip hoverStartSound;
- // Use this for initialization
- void Start()
- {
- if (!zedController) zedController = GetComponentInParent<ZEDControllerTracker_DemoInputs>();
- }
- // Update is called once per frame
- void Update()
- {
- CheckListElementsForValidity();
- CheckHovers();
- }
- private void OnTriggerEnter(Collider collision)
- {
- IXRHoverable newhoverable = collision.gameObject.GetComponent<IXRHoverable>();
- if (newhoverable != null && !collidingHoverables.Contains(newhoverable)) collidingHoverables.Add(newhoverable);
- IXRClickable newclickable = collision.gameObject.GetComponent<IXRClickable>();
- if (newclickable != null && !collidingClickables.Contains(newclickable)) collidingClickables.Add(newclickable);
- IXRGrabbable newgrabbable = collision.gameObject.GetComponent<IXRGrabbable>();
- if (newgrabbable != null && !collidingGrabbables.Contains(newgrabbable)) collidingGrabbables.Add(newgrabbable);
- }
- private void OnTriggerExit(Collider collision)
- {
- IXRHoverable newhoverable = collision.gameObject.GetComponent<IXRHoverable>();
- if (newhoverable != null && collidingHoverables.Contains(newhoverable)) collidingHoverables.Remove(newhoverable);
- IXRClickable newclickable = collision.gameObject.GetComponent<IXRClickable>();
- if (newclickable != null && collidingClickables.Contains(newclickable)) collidingClickables.Remove(newclickable);
- IXRGrabbable newgrabbable = collision.gameObject.GetComponent<IXRGrabbable>();
- if (newgrabbable != null && collidingGrabbables.Contains(newgrabbable)) collidingGrabbables.Remove(newgrabbable);
- }
- private void CheckHovers()
- {
- //If we're grabbing something, we shouldn't be hovering over anything.
- if(grabbingObject != null)
- {
- if(hoveringObject != null)
- {
- if(!Equals(hoveringObject, null)) hoveringObject.OnHoverEnd();
- hoveringObject = null;
- }
- return;
- }
- float nearestdist = Mathf.Infinity;
- IXRHoverable newhover = null;
- foreach(IXRHoverable hover in collidingHoverables)
- {
- float dist = Vector3.Distance(transform.position, hover.GetTransform().position);
- if (dist < nearestdist) newhover = hover;
- }
- if(hoveringObject != newhover)
- {
- if (hoveringObject != null && !hoveringObject.Equals(null))
- {
- hoveringObject.OnHoverEnd();
- }
- if(newhover != null)
- {
- PlaySoundIfValid(hoverStartSound);
- newhover.OnHoverStart();
- }
- hoveringObject = newhover;
- }
- }
- /// <summary>
- /// Checks the interface lists to make sure that they all still exist. Otherwise, if something is destroyed
- /// or disabled while still in range, we'll still try to interact with it.
- /// </summary>
- private void CheckListElementsForValidity()
- {
- List<IXRHoverable> toremove = new List<IXRHoverable>();
- foreach(IXRHoverable hoverable in collidingHoverables)
- {
- if(hoverable.Equals(null))
- {
- toremove.Add(hoverable);
- continue;
- }
- Collider col = hoverable.GetTransform().GetComponent<Collider>();
- if(col == null || col.enabled == false)
- {
- toremove.Add(hoverable);
- }
- }
- foreach (IXRHoverable deadhoverable in toremove)
- {
- collidingHoverables.Remove(deadhoverable);
- }
- }
- public void TryClick()
- {
- if (hoveringObject == null) return;
- IXRClickable newclick = hoveringObject.GetTransform().GetComponent<IXRClickable>();
- if (newclick == null) return;
- PlaySoundIfValid(clickSound);
- newclick.OnClick(this);
- }
- public void TryGrab()
- {
- if (grabbingObject != null)
- {
- Debug.Log("Somehow grabbed something while already grabbing something else. Calling ReleaseGrab on that object.");
- ReleaseGrab();
- }
- if (hoveringObject == null) return;
- IXRGrabbable newgrab = hoveringObject.GetTransform().GetComponent<IXRGrabbable>();
- if (newgrab == null) return;
- if (!Equals(hoveringObject, null)) hoveringObject.OnHoverEnd();
- hoveringObject = null;
- newgrab.OnGrabStart(transform);
- grabbingObject = newgrab;
- PlaySoundIfValid(grabStartSound);
- }
- public void ReleaseGrab()
- {
- if (grabbingObject == null) return;
- grabbingObject.OnGrabEnd();
- grabbingObject = null;
- PlaySoundIfValid(grabEndSound);
- }
- /// <summary>
- /// Plays the given clip, but in a temporary gameobject that appears where the ball is.
- /// This lets the sound finish playing even if this object is disabled, such as if you press
- /// the switch hands button.
- /// </summary>
- private void PlaySoundIfValid(AudioClip clip)
- {
- if (clip == null) return;
- //audioSource.PlayOneShot(clip);
- GameObject soundgo = new GameObject("Temp Audio Object: " + clip.name);
- soundgo.transform.position = transform.position;
- TempAudioObject sound = soundgo.AddComponent<TempAudioObject>();
- sound.Setup(clip);
- }
- private void OnDisable()
- {
- if(hoveringObject != null)
- {
- if (!Equals(hoveringObject, null)) hoveringObject.OnHoverEnd();
- hoveringObject = null;
- }
- if(grabbingObject != null)
- {
- grabbingObject.OnGrabEnd();
- grabbingObject = null;
- }
- collidingHoverables.Clear();
- collidingGrabbables.Clear();
- collidingClickables.Clear();
- }
- }
- public interface IXRHoverable
- {
- Transform GetTransform();
- void OnHoverStart();
- void OnHoverEnd();
- }
- public interface IXRClickable
- {
- Transform GetTransform();
- void OnClick(ZEDXRGrabber clicker);
- }
- public interface IXRGrabbable
- {
- Transform GetTransform();
- void OnGrabStart(Transform grabtransform);
- void OnGrabEnd();
- }
|