CalloutGazeController.cs 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. using System;
  2. using Unity.XR.CoreUtils;
  3. using UnityEngine;
  4. using UnityEngine.Events;
  5. using UnityEngine.Serialization;
  6. namespace Unity.VRTemplate
  7. {
  8. /// <summary>
  9. /// Fires events when this object is is within the field of view of the gaze transform. This is currently used to
  10. /// hide and show tooltip callouts on the controllers when the controllers are within the field of view.
  11. /// </summary>
  12. public class CalloutGazeController : MonoBehaviour
  13. {
  14. [SerializeField, Tooltip("The transform which the forward direction will be used to evaluate as the gaze direction.")]
  15. Transform m_GazeTransform;
  16. [SerializeField, Tooltip("Threshold for the dot product when determining if the Gaze Transform is facing this object. The lower the threshold, the wider the field of view."), Range(0.0f, 1.0f)]
  17. float m_FacingThreshold = 0.85f;
  18. [SerializeField, Tooltip("Events fired when the Gaze Transform begins facing this game object")]
  19. UnityEvent m_FacingEntered;
  20. [SerializeField, Tooltip("Events fired when the Gaze Transform stops facing this game object")]
  21. UnityEvent m_FacingExited;
  22. [SerializeField, Tooltip("Distance threshold for movement in a single frame that determines a large movement that will trigger Facing Exited events.")]
  23. float m_LargeMovementDistanceThreshold = 0.05f;
  24. [SerializeField, Tooltip("Cool down time after a large movement for Facing Entered events to fire again.")]
  25. float m_LargeMovementCoolDownTime = 0.25f;
  26. bool m_IsFacing;
  27. float m_LargeMovementCoolDown;
  28. Vector3 m_LastPosition;
  29. void Update()
  30. {
  31. if (!m_GazeTransform)
  32. return;
  33. CheckLargeMovement();
  34. if (m_LargeMovementCoolDown < m_LargeMovementCoolDownTime)
  35. return;
  36. var dotProduct = Vector3.Dot(m_GazeTransform.forward, (transform.position - m_GazeTransform.position).normalized);
  37. if (dotProduct > m_FacingThreshold && !m_IsFacing)
  38. FacingEntered();
  39. else if (dotProduct < m_FacingThreshold && m_IsFacing)
  40. FacingExited();
  41. }
  42. void CheckLargeMovement()
  43. {
  44. // Check if there is large movement
  45. var currentPosition = transform.position;
  46. var positionDelta = Mathf.Abs(Vector3.Distance(m_LastPosition, currentPosition));
  47. if (positionDelta > m_LargeMovementDistanceThreshold)
  48. {
  49. m_LargeMovementCoolDown = 0.0f;
  50. FacingExited();
  51. }
  52. m_LargeMovementCoolDown += Time.deltaTime;
  53. m_LastPosition = currentPosition;
  54. }
  55. void FacingEntered()
  56. {
  57. m_IsFacing = true;
  58. m_FacingEntered.Invoke();
  59. }
  60. void FacingExited()
  61. {
  62. m_IsFacing = false;
  63. m_FacingExited.Invoke();
  64. }
  65. }
  66. }