ARContactSpawnTrigger.cs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. #if AR_FOUNDATION_PRESENT
  2. using UnityEngine.Events;
  3. using UnityEngine.XR.ARSubsystems;
  4. using UnityEngine.XR.ARFoundation;
  5. using UnityEngine.XR.Interaction.Toolkit.Interactors;
  6. namespace UnityEngine.XR.Interaction.Toolkit.Samples.ARStarterAssets
  7. {
  8. /// <summary>
  9. /// Spawns an object on physics trigger enter with an <see cref="ARPlane"/>, at the point of contact on the plane.
  10. /// </summary>
  11. [RequireComponent(typeof(Rigidbody))]
  12. public class ARContactSpawnTrigger : MonoBehaviour
  13. {
  14. [SerializeField]
  15. [Tooltip("If enabled, spawning will be blocked if the active interactor in the associated XR Interaction Group is hovering or selecting an interactable object.")]
  16. bool m_BlockSpawnDuringInteraction;
  17. /// <summary>
  18. /// If enabled, spawning will be blocked if the active interactor in the associated <see cref="interactionGroup"/> is hovering or selecting an interactable object.
  19. /// </summary>
  20. public bool blockSpawnDuringInteraction
  21. {
  22. get => m_BlockSpawnDuringInteraction;
  23. set => m_BlockSpawnDuringInteraction = value;
  24. }
  25. [SerializeField]
  26. [Tooltip("XR Interaction Group associated with this contact spawn trigger.")]
  27. XRInteractionGroup m_InteractionGroup;
  28. /// <summary>
  29. /// XR Interaction Group associated with this contact spawn trigger. Spawning will be blocked if an interactor from this XR Interaction Group is
  30. /// hovering or selecting and interactable and <see cref="blockSpawnDuringInteraction"/> is enabled.
  31. /// </summary>
  32. /// <remarks>If <see langword="null"/>, this scripts attempts to find an <see cref="XRInteractionGroup"/> component on the parent.</remarks>
  33. public XRInteractionGroup interactionGroup
  34. {
  35. get => m_InteractionGroup;
  36. set => m_InteractionGroup = value;
  37. }
  38. [SerializeField]
  39. [Tooltip("Whether to require that the AR Plane has an alignment of horizontal up to spawn on it.")]
  40. bool m_RequireHorizontalUpSurface;
  41. /// <summary>
  42. /// Whether to require that the <see cref="ARPlane"/> has an alignment of <see cref="PlaneAlignment.HorizontalUp"/> to spawn on it.
  43. /// </summary>
  44. public bool requireHorizontalUpSurface
  45. {
  46. get => m_RequireHorizontalUpSurface;
  47. set => m_RequireHorizontalUpSurface = value;
  48. }
  49. /// <summary>
  50. /// Calls the methods in its invocation list when an object is spawned.
  51. /// </summary>
  52. /// <remarks>
  53. /// The first event parameter corresponds to the spawn position in world space
  54. /// and the second event parameter corresponds to the vector normal to the surface.
  55. /// </remarks>
  56. public UnityEvent<Vector3, Vector3> objectSpawnTriggered
  57. {
  58. get => m_ObjectSpawnTriggered;
  59. set => m_ObjectSpawnTriggered = value;
  60. }
  61. [Header("Events")]
  62. [SerializeField]
  63. [Tooltip("Calls the methods in its invocation list when an object is spawned.")]
  64. UnityEvent<Vector3, Vector3> m_ObjectSpawnTriggered = new UnityEvent<Vector3, Vector3>();
  65. /// <summary>
  66. /// See <see cref="MonoBehaviour"/>.
  67. /// </summary>
  68. void Start()
  69. {
  70. if (m_InteractionGroup == null)
  71. {
  72. m_InteractionGroup = GetComponentInParent<XRInteractionGroup>();
  73. if (m_BlockSpawnDuringInteraction && m_InteractionGroup == null)
  74. Debug.LogWarning("Interaction group could be found. Spawning objects will not be blocked during hover or select interaction.", this);
  75. }
  76. }
  77. /// <summary>
  78. /// See <see cref="MonoBehaviour"/>.
  79. /// </summary>
  80. void OnTriggerEnter(Collider other)
  81. {
  82. if ((blockSpawnDuringInteraction && IsInteractionBlockingSpawn()) ||
  83. !TryGetSpawnSurfaceData(other, out var surfacePosition, out var surfaceNormal))
  84. return;
  85. var infinitePlane = new Plane(surfaceNormal, surfacePosition);
  86. var contactPoint = infinitePlane.ClosestPointOnPlane(transform.position);
  87. m_ObjectSpawnTriggered.Invoke(contactPoint, surfaceNormal);
  88. }
  89. /// <summary>
  90. /// Tries to get the surface position and normal from an object to potentially spawn on.
  91. /// </summary>
  92. /// <param name="objectCollider">The collider of the object to potentially spawn on.</param>
  93. /// <param name="surfacePosition">The potential world position of the spawn surface.</param>
  94. /// <param name="surfaceNormal">The potential normal of the spawn surface.</param>
  95. /// <returns>Returns <see langword="true"/> if <paramref name="objectCollider"/> is a valid spawn surface,
  96. /// otherwise returns <see langword="false"/>.</returns>
  97. public bool TryGetSpawnSurfaceData(Collider objectCollider, out Vector3 surfacePosition, out Vector3 surfaceNormal)
  98. {
  99. surfacePosition = default;
  100. surfaceNormal = default;
  101. var arPlane = objectCollider.GetComponent<ARPlane>();
  102. if (arPlane == null)
  103. return false;
  104. if (m_RequireHorizontalUpSurface && arPlane.alignment != PlaneAlignment.HorizontalUp)
  105. return false;
  106. surfaceNormal = arPlane.normal;
  107. surfacePosition = arPlane.center;
  108. return true;
  109. }
  110. bool IsInteractionBlockingSpawn()
  111. {
  112. if (m_InteractionGroup != null && m_InteractionGroup.activeInteractor != null)
  113. {
  114. var hoverInteractor = (IXRHoverInteractor)m_InteractionGroup.activeInteractor;
  115. var selectInteractor = (IXRSelectInteractor)m_InteractionGroup.activeInteractor;
  116. var isHovering = (hoverInteractor != null) && hoverInteractor.hasHover;
  117. var isSelecting = (selectInteractor != null) && selectInteractor.hasSelection;
  118. return isHovering || isSelecting;
  119. }
  120. return false;
  121. }
  122. }
  123. }
  124. #endif