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.

326 lines
13 KiB

  1. // Slingshot Jump|Locomotion|20121
  2. namespace VRTK
  3. {
  4. using UnityEngine;
  5. /// <summary>
  6. /// Event Payload
  7. /// </summary>
  8. /// <param name="sender">this object</param>
  9. public delegate void SlingshotJumpEventHandler(object sender);
  10. /// <summary>
  11. /// Provides the ability for the SDK Camera Rig to be thrown around with a jumping motion by slingshotting based on the pull back of each valid controller.
  12. /// </summary>
  13. /// <remarks>
  14. /// **Required Components:**
  15. /// * `VRTK_PlayerClimb` - A Player Climb script for dealing with the physical throwing of the play area as if throwing off an invisible climbed object.
  16. /// * `VRTK_BodyPhysics` - A Body Physics script to deal with the effects of physics and gravity on the play area.
  17. ///
  18. /// **Optional Components:**
  19. /// * `VRTK_BasicTeleport` - A Teleporter script to use when snapping the play area to the nearest floor when releasing from grab.
  20. /// * `VRTK_HeadsetCollision` - A Headset Collision script to determine when the headset is colliding with geometry to know when to reset to a valid location.
  21. /// * `VRTK_PositionRewind` - A Position Rewind script to utilise when resetting to a valid location upon ungrabbing whilst colliding with geometry.
  22. ///
  23. /// **Script Usage:**
  24. /// * Place the `VRTK_SlingshotJump` script on the same GameObject as the `VRTK_PlayerClimb` script.
  25. /// </remarks>
  26. /// <example>
  27. /// `VRTK/Examples/037_CameraRig_ClimbingFalling` shows how to set up a scene with slingshot jumping. This script just needs to be added to the PlayArea object and the requested forces and buttons set.
  28. /// </example>
  29. [AddComponentMenu("VRTK/Scripts/Locomotion/VRTK_SlingshotJump")]
  30. public class VRTK_SlingshotJump : MonoBehaviour
  31. {
  32. [Header("SlingshotJump Settings")]
  33. [Tooltip("How close together the button releases have to be to initiate a jump.")]
  34. public float releaseWindowTime = 0.5f;
  35. [Tooltip("Multiplier that increases the jump strength.")]
  36. public float velocityMultiplier = 5.0f;
  37. [Tooltip("The maximum velocity a jump can be.")]
  38. public float velocityMax = 8.0f;
  39. [Tooltip("The button that will initiate the slingshot move.")]
  40. [SerializeField]
  41. protected VRTK_ControllerEvents.ButtonAlias activationButton = VRTK_ControllerEvents.ButtonAlias.GripPress;
  42. [Tooltip("The button that will cancel an already tensioned sling shot.")]
  43. [SerializeField]
  44. protected VRTK_ControllerEvents.ButtonAlias cancelButton = VRTK_ControllerEvents.ButtonAlias.Undefined;
  45. [Tooltip("The Body Physics script to deal with the physics and gravity of the play area. If the script is being applied onto an object that already has a VRTK_BodyPhysics component, this parameter can be left blank as it will be auto populated by the script at runtime.")]
  46. [SerializeField]
  47. protected VRTK_BodyPhysics bodyPhysics;
  48. [Tooltip("The Player Climb script to deal ability to throw the play area. If the script is being applied onto an object that already has a VRTK_PlayerClimb component, this parameter can be left blank as it will be auto populated by the script at runtime.")]
  49. [SerializeField]
  50. protected VRTK_PlayerClimb playerClimb;
  51. [Tooltip("The Teleporter script to deal play area teleporting. If the script is being applied onto an object that already has a VRTK_BasicTeleport component, this parameter can be left blank as it will be auto populated by the script at runtime.")]
  52. [SerializeField]
  53. protected VRTK_BasicTeleport teleporter;
  54. /// <summary>
  55. /// Emitted when a slingshot jump occurs
  56. /// </summary>
  57. public event SlingshotJumpEventHandler SlingshotJumped;
  58. protected Transform playArea;
  59. protected Vector3 leftStartAimPosition;
  60. protected Vector3 leftReleasePosition;
  61. protected bool leftIsAiming;
  62. protected Vector3 rightStartAimPosition;
  63. protected Vector3 rightReleasePosition;
  64. protected bool rightIsAiming;
  65. protected VRTK_ControllerEvents leftControllerEvents;
  66. protected VRTK_ControllerEvents rightControllerEvents;
  67. protected VRTK_InteractGrab leftControllerGrab;
  68. protected VRTK_InteractGrab rightControllerGrab;
  69. protected bool leftButtonReleased;
  70. protected bool rightButtonReleased;
  71. protected float countDownEndTime;
  72. /// <summary>
  73. /// The SetActivationButton method gets the button used to activate a slingshot jump.
  74. /// </summary>
  75. /// <returns>Returns the button used for slingshot activation.</returns>
  76. public virtual VRTK_ControllerEvents.ButtonAlias GetActivationButton()
  77. {
  78. return activationButton;
  79. }
  80. /// <summary>
  81. /// The SetActivationButton method sets the button used to activate a slingshot jump.
  82. /// </summary>
  83. /// <param name="button">The controller button to use to activate the jump.</param>
  84. public virtual void SetActivationButton(VRTK_ControllerEvents.ButtonAlias button)
  85. {
  86. InitControllerListeners(false);
  87. activationButton = button;
  88. InitControllerListeners(true);
  89. }
  90. /// <summary>
  91. /// The GetCancelButton method gets the button used to cancel a slingshot jump.
  92. /// </summary>
  93. /// <returns>Returns the button used to cancel a slingshot jump.</returns>
  94. public virtual VRTK_ControllerEvents.ButtonAlias GetCancelButton()
  95. {
  96. return cancelButton;
  97. }
  98. /// <summary>
  99. /// The SetCancelButton method sets the button used to cancel a slingshot jump.
  100. /// </summary>
  101. /// <param name="button">The controller button to use to cancel the jump.</param>
  102. public virtual void SetCancelButton(VRTK_ControllerEvents.ButtonAlias button)
  103. {
  104. InitControllerListeners(false);
  105. cancelButton = button;
  106. InitControllerListeners(true);
  107. }
  108. protected virtual void Awake()
  109. {
  110. bodyPhysics = (bodyPhysics != null ? bodyPhysics : FindObjectOfType<VRTK_BodyPhysics>());
  111. playerClimb = (playerClimb != null ? playerClimb : FindObjectOfType<VRTK_PlayerClimb>());
  112. VRTK_SDKManager.AttemptAddBehaviourToToggleOnLoadedSetupChange(this);
  113. }
  114. protected virtual void OnEnable()
  115. {
  116. InitListeners(true);
  117. playArea = VRTK_DeviceFinder.PlayAreaTransform();
  118. }
  119. protected virtual void OnDisable()
  120. {
  121. UnAim();
  122. InitListeners(false);
  123. }
  124. protected virtual void OnDestroy()
  125. {
  126. VRTK_SDKManager.AttemptRemoveBehaviourToToggleOnLoadedSetupChange(this);
  127. }
  128. protected virtual void LeftButtonPressed(object sender, ControllerInteractionEventArgs e)
  129. {
  130. // Check for new left aim
  131. if (!leftIsAiming && !IsClimbing())
  132. {
  133. leftIsAiming = true;
  134. leftStartAimPosition = playArea.InverseTransformPoint(leftControllerEvents.gameObject.transform.position);
  135. }
  136. }
  137. protected virtual void RightButtonPressed(object sender, ControllerInteractionEventArgs e)
  138. {
  139. // Check for new right aim
  140. if (!rightIsAiming && !IsClimbing())
  141. {
  142. rightIsAiming = true;
  143. rightStartAimPosition = playArea.InverseTransformPoint(rightControllerEvents.gameObject.transform.position);
  144. }
  145. }
  146. protected virtual void LeftButtonReleased(object sender, ControllerInteractionEventArgs e)
  147. {
  148. // Check for release states
  149. if (leftIsAiming)
  150. {
  151. leftReleasePosition = playArea.InverseTransformPoint(leftControllerEvents.gameObject.transform.position);
  152. if (!rightButtonReleased)
  153. {
  154. countDownEndTime = Time.time + releaseWindowTime;
  155. }
  156. leftButtonReleased = true;
  157. }
  158. CheckForReset();
  159. CheckForJump();
  160. }
  161. protected virtual void RightButtonReleased(object sender, ControllerInteractionEventArgs e)
  162. {
  163. // Check for release states
  164. if (rightIsAiming)
  165. {
  166. rightReleasePosition = playArea.InverseTransformPoint(rightControllerEvents.gameObject.transform.position);
  167. if (!leftButtonReleased)
  168. {
  169. countDownEndTime = Time.time + releaseWindowTime;
  170. }
  171. rightButtonReleased = true;
  172. }
  173. CheckForReset();
  174. CheckForJump();
  175. }
  176. protected virtual void CancelButtonPressed(object sender, ControllerInteractionEventArgs e)
  177. {
  178. UnAim();
  179. }
  180. protected virtual void CheckForReset()
  181. {
  182. if ((leftButtonReleased || rightButtonReleased) && Time.time > countDownEndTime)
  183. {
  184. UnAim();
  185. }
  186. }
  187. protected virtual void CheckForJump()
  188. {
  189. if (leftButtonReleased && rightButtonReleased && !bodyPhysics.IsFalling())
  190. {
  191. Vector3 leftDir = leftStartAimPosition - leftReleasePosition;
  192. Vector3 rightDir = rightStartAimPosition - rightReleasePosition;
  193. Vector3 localJumpDir = leftDir + rightDir;
  194. Vector3 worldJumpDir = playArea.transform.TransformVector(localJumpDir);
  195. Vector3 jumpVector = worldJumpDir * velocityMultiplier;
  196. if (jumpVector.magnitude > velocityMax)
  197. {
  198. jumpVector = jumpVector.normalized * velocityMax;
  199. }
  200. bodyPhysics.ApplyBodyVelocity(jumpVector, true, true);
  201. UnAim();
  202. OnSlingshotJumped();
  203. }
  204. }
  205. protected void OnSlingshotJumped()
  206. {
  207. if (SlingshotJumped != null)
  208. {
  209. SlingshotJumped(this);
  210. }
  211. }
  212. protected void InitListeners(bool state)
  213. {
  214. InitTeleportListener(state);
  215. InitControllerListeners(state);
  216. }
  217. protected void InitTeleportListener(bool state)
  218. {
  219. teleporter = (teleporter != null ? teleporter : FindObjectOfType<VRTK_BasicTeleport>());
  220. if (teleporter != null)
  221. {
  222. if (state == true)
  223. {
  224. teleporter.Teleporting += new TeleportEventHandler(OnTeleport);
  225. }
  226. else
  227. {
  228. teleporter.Teleporting -= new TeleportEventHandler(OnTeleport);
  229. }
  230. }
  231. }
  232. protected void InitControllerListeners(bool state)
  233. {
  234. InitControllerListener(state, VRTK_DeviceFinder.GetControllerLeftHand(), ref leftControllerEvents, ref leftControllerGrab, LeftButtonPressed, LeftButtonReleased);
  235. InitControllerListener(state, VRTK_DeviceFinder.GetControllerRightHand(), ref rightControllerEvents, ref rightControllerGrab, RightButtonPressed, RightButtonReleased);
  236. }
  237. protected void InitControllerListener(bool state, GameObject controller, ref VRTK_ControllerEvents events, ref VRTK_InteractGrab grab,
  238. ControllerInteractionEventHandler triggerPressed, ControllerInteractionEventHandler triggerReleased)
  239. {
  240. if (controller != null)
  241. {
  242. events = controller.GetComponentInChildren<VRTK_ControllerEvents>();
  243. grab = controller.GetComponentInChildren<VRTK_InteractGrab>();
  244. if (events != null)
  245. {
  246. if (state == true)
  247. {
  248. events.SubscribeToButtonAliasEvent(activationButton, true, triggerPressed);
  249. events.SubscribeToButtonAliasEvent(activationButton, false, triggerReleased);
  250. if (cancelButton != VRTK_ControllerEvents.ButtonAlias.Undefined)
  251. {
  252. events.SubscribeToButtonAliasEvent(cancelButton, true, CancelButtonPressed);
  253. }
  254. }
  255. else
  256. {
  257. events.UnsubscribeToButtonAliasEvent(activationButton, true, triggerPressed);
  258. events.UnsubscribeToButtonAliasEvent(activationButton, false, triggerReleased);
  259. if (cancelButton != VRTK_ControllerEvents.ButtonAlias.Undefined)
  260. {
  261. events.UnsubscribeToButtonAliasEvent(cancelButton, true, CancelButtonPressed);
  262. }
  263. }
  264. }
  265. }
  266. }
  267. protected void OnTeleport(object sender, DestinationMarkerEventArgs e)
  268. {
  269. UnAim();
  270. }
  271. protected void UnAim()
  272. {
  273. leftIsAiming = false;
  274. rightIsAiming = false;
  275. leftButtonReleased = false;
  276. rightButtonReleased = false;
  277. }
  278. protected bool IsClimbing()
  279. {
  280. return (playerClimb != null && playerClimb.IsClimbing());
  281. }
  282. }
  283. }