Assignment for RMIT Mixed Reality in 2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

202 lines
7.9 KiB

  1. // Dash Teleport|Locomotion|20030
  2. namespace VRTK
  3. {
  4. using UnityEngine;
  5. using System.Collections;
  6. /// <summary>
  7. /// Event Payload
  8. /// </summary>
  9. /// <param name="hits">An array of RaycastHits that the CapsuleCast has collided with.</param>
  10. public struct DashTeleportEventArgs
  11. {
  12. public RaycastHit[] hits;
  13. }
  14. /// <summary>
  15. /// Event Payload
  16. /// </summary>
  17. /// <param name="sender">this object</param>
  18. /// <param name="e"><see cref="DashTeleportEventArgs"/></param>
  19. public delegate void DashTeleportEventHandler(object sender, DashTeleportEventArgs e);
  20. /// <summary>
  21. /// Updates the `x/y/z` position of the SDK Camera Rig with a lerp to the new position creating a dash effect.
  22. /// </summary>
  23. /// <remarks>
  24. /// **Script Usage:**
  25. /// * Place the `VRTK_DashTeleport` script on any active scene GameObject.
  26. ///
  27. /// **Script Dependencies:**
  28. /// * An optional Destination Marker (such as a Pointer) to set the destination of the teleport location.
  29. /// </remarks>
  30. /// <example>
  31. /// `VRTK/Examples/038_CameraRig_DashTeleport` shows how to turn off the mesh renderers of objects that are in the way during the dash.
  32. /// </example>
  33. [AddComponentMenu("VRTK/Scripts/Locomotion/VRTK_DashTeleport")]
  34. public class VRTK_DashTeleport : VRTK_HeightAdjustTeleport
  35. {
  36. [Header("Dash Settings")]
  37. [Tooltip("The fixed time it takes to dash to a new position.")]
  38. public float normalLerpTime = 0.1f;
  39. [Tooltip("The minimum speed for dashing in meters per second.")]
  40. public float minSpeedMps = 50.0f;
  41. [Tooltip("The Offset of the CapsuleCast above the camera.")]
  42. public float capsuleTopOffset = 0.2f;
  43. [Tooltip("The Offset of the CapsuleCast below the camera.")]
  44. public float capsuleBottomOffset = 0.5f;
  45. [Tooltip("The radius of the CapsuleCast.")]
  46. public float capsuleRadius = 0.5f;
  47. /// <summary>
  48. /// Emitted when the CapsuleCast towards the target has found that obstacles are in the way.
  49. /// </summary>
  50. public event DashTeleportEventHandler WillDashThruObjects;
  51. /// <summary>
  52. /// Emitted when obstacles have been crossed and the dash has ended.
  53. /// </summary>
  54. public event DashTeleportEventHandler DashedThruObjects;
  55. protected float minDistanceForNormalLerp;
  56. protected float lerpTime = 0.1f;
  57. protected Coroutine attemptLerpRoutine;
  58. public virtual void OnWillDashThruObjects(DashTeleportEventArgs e)
  59. {
  60. if (WillDashThruObjects != null)
  61. {
  62. WillDashThruObjects(this, e);
  63. }
  64. }
  65. public virtual void OnDashedThruObjects(DashTeleportEventArgs e)
  66. {
  67. if (DashedThruObjects != null)
  68. {
  69. DashedThruObjects(this, e);
  70. }
  71. }
  72. protected override void OnEnable()
  73. {
  74. base.OnEnable();
  75. minDistanceForNormalLerp = minSpeedMps * normalLerpTime;
  76. }
  77. protected override void OnDisable()
  78. {
  79. base.OnDisable();
  80. if (attemptLerpRoutine != null)
  81. {
  82. StopCoroutine(attemptLerpRoutine);
  83. attemptLerpRoutine = null;
  84. }
  85. }
  86. protected override Vector3 SetNewPosition(Vector3 position, Transform target, bool forceDestinationPosition)
  87. {
  88. return CheckTerrainCollision(position, target, forceDestinationPosition);
  89. }
  90. protected override Quaternion SetNewRotation(Quaternion? rotation)
  91. {
  92. if (ValidRigObjects())
  93. {
  94. return (rotation != null ? (Quaternion)rotation : playArea.rotation);
  95. }
  96. return Quaternion.identity;
  97. }
  98. protected override void StartTeleport(object sender, DestinationMarkerEventArgs e)
  99. {
  100. base.StartTeleport(sender, e);
  101. }
  102. protected override void ProcessOrientation(object sender, DestinationMarkerEventArgs e, Vector3 targetPosition, Quaternion targetRotation)
  103. {
  104. if (ValidRigObjects())
  105. {
  106. Vector3 finalPosition = CalculateOffsetPosition(targetPosition, targetRotation);
  107. attemptLerpRoutine = StartCoroutine(lerpToPosition(sender, e, playArea.position, finalPosition, playArea.rotation, targetRotation));
  108. }
  109. }
  110. protected virtual Vector3 CalculateOffsetPosition(Vector3 targetPosition, Quaternion targetRotation)
  111. {
  112. if (!headsetPositionCompensation)
  113. {
  114. return targetPosition;
  115. }
  116. Vector3 playerOffset = new Vector3(headset.position.x - playArea.position.x, 0, headset.position.z - playArea.position.z);
  117. Quaternion relativeRotation = Quaternion.Inverse(playArea.rotation) * targetRotation;
  118. Vector3 adjustedOffset = relativeRotation * playerOffset;
  119. return targetPosition - (adjustedOffset - playerOffset);
  120. }
  121. protected override void EndTeleport(object sender, DestinationMarkerEventArgs e)
  122. {
  123. }
  124. protected virtual IEnumerator lerpToPosition(object sender, DestinationMarkerEventArgs e, Vector3 startPosition, Vector3 targetPosition, Quaternion startRotation, Quaternion targetRotation)
  125. {
  126. enableTeleport = false;
  127. bool gameObjectInTheWay = false;
  128. // Find the objects we will be dashing through and broadcast them via events
  129. Vector3 eyeCameraPosition = headset.transform.position;
  130. Vector3 eyeCameraPositionOnGround = new Vector3(eyeCameraPosition.x, playArea.position.y, eyeCameraPosition.z);
  131. Vector3 eyeCameraRelativeToRig = eyeCameraPosition - playArea.position;
  132. Vector3 targetEyeCameraPosition = targetPosition + eyeCameraRelativeToRig;
  133. Vector3 direction = (targetEyeCameraPosition - eyeCameraPosition).normalized;
  134. Vector3 bottomPoint = eyeCameraPositionOnGround + (Vector3.up * capsuleBottomOffset) + direction;
  135. Vector3 topPoint = eyeCameraPosition + (Vector3.up * capsuleTopOffset) + direction;
  136. float maxDistance = Vector3.Distance(playArea.position, targetPosition - direction * 0.5f);
  137. RaycastHit[] allHits = Physics.CapsuleCastAll(bottomPoint, topPoint, capsuleRadius, direction, maxDistance);
  138. for (int i = 0; i < allHits.Length; i++)
  139. {
  140. gameObjectInTheWay = (allHits[i].collider.gameObject != e.target.gameObject ? true : false);
  141. }
  142. if (gameObjectInTheWay)
  143. {
  144. OnWillDashThruObjects(SetDashTeleportEvent(allHits));
  145. }
  146. lerpTime = (maxDistance >= minDistanceForNormalLerp ? normalLerpTime : VRTK_SharedMethods.DividerToMultiplier(minSpeedMps) * maxDistance);
  147. float elapsedTime = 0f;
  148. float currentLerpedTime = 0f;
  149. WaitForEndOfFrame delayInstruction = new WaitForEndOfFrame();
  150. while (currentLerpedTime < 1f)
  151. {
  152. playArea.position = Vector3.Lerp(startPosition, targetPosition, currentLerpedTime);
  153. playArea.rotation = Quaternion.Lerp(startRotation, targetRotation, currentLerpedTime);
  154. elapsedTime += Time.deltaTime;
  155. currentLerpedTime = elapsedTime / lerpTime;
  156. yield return delayInstruction;
  157. }
  158. playArea.position = targetPosition;
  159. playArea.rotation = targetRotation;
  160. if (gameObjectInTheWay)
  161. {
  162. OnDashedThruObjects(SetDashTeleportEvent(allHits));
  163. }
  164. base.EndTeleport(sender, e);
  165. gameObjectInTheWay = false;
  166. enableTeleport = true;
  167. }
  168. protected virtual DashTeleportEventArgs SetDashTeleportEvent(RaycastHit[] hits)
  169. {
  170. DashTeleportEventArgs e;
  171. e.hits = hits;
  172. return e;
  173. }
  174. }
  175. }