123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- // Slingshot Jump|Locomotion|20121
- namespace VRTK
- {
- using UnityEngine;
- /// <summary>
- /// Event Payload
- /// </summary>
- /// <param name="sender">this object</param>
- public delegate void SlingshotJumpEventHandler(object sender);
- /// <summary>
- /// 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.
- /// </summary>
- /// <remarks>
- /// **Required Components:**
- /// * `VRTK_PlayerClimb` - A Player Climb script for dealing with the physical throwing of the play area as if throwing off an invisible climbed object.
- /// * `VRTK_BodyPhysics` - A Body Physics script to deal with the effects of physics and gravity on the play area.
- ///
- /// **Optional Components:**
- /// * `VRTK_BasicTeleport` - A Teleporter script to use when snapping the play area to the nearest floor when releasing from grab.
- /// * `VRTK_HeadsetCollision` - A Headset Collision script to determine when the headset is colliding with geometry to know when to reset to a valid location.
- /// * `VRTK_PositionRewind` - A Position Rewind script to utilise when resetting to a valid location upon ungrabbing whilst colliding with geometry.
- ///
- /// **Script Usage:**
- /// * Place the `VRTK_SlingshotJump` script on the same GameObject as the `VRTK_PlayerClimb` script.
- /// </remarks>
- /// <example>
- /// `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.
- /// </example>
- [AddComponentMenu("VRTK/Scripts/Locomotion/VRTK_SlingshotJump")]
- public class VRTK_SlingshotJump : MonoBehaviour
- {
- [Header("SlingshotJump Settings")]
- [Tooltip("How close together the button releases have to be to initiate a jump.")]
- public float releaseWindowTime = 0.5f;
- [Tooltip("Multiplier that increases the jump strength.")]
- public float velocityMultiplier = 5.0f;
- [Tooltip("The maximum velocity a jump can be.")]
- public float velocityMax = 8.0f;
- [Tooltip("The button that will initiate the slingshot move.")]
- [SerializeField]
- protected VRTK_ControllerEvents.ButtonAlias activationButton = VRTK_ControllerEvents.ButtonAlias.GripPress;
- [Tooltip("The button that will cancel an already tensioned sling shot.")]
- [SerializeField]
- protected VRTK_ControllerEvents.ButtonAlias cancelButton = VRTK_ControllerEvents.ButtonAlias.Undefined;
- [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.")]
- [SerializeField]
- protected VRTK_BodyPhysics bodyPhysics;
- [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.")]
- [SerializeField]
- protected VRTK_PlayerClimb playerClimb;
- [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.")]
- [SerializeField]
- protected VRTK_BasicTeleport teleporter;
- /// <summary>
- /// Emitted when a slingshot jump occurs
- /// </summary>
- public event SlingshotJumpEventHandler SlingshotJumped;
- protected Transform playArea;
- protected Vector3 leftStartAimPosition;
- protected Vector3 leftReleasePosition;
- protected bool leftIsAiming;
- protected Vector3 rightStartAimPosition;
- protected Vector3 rightReleasePosition;
- protected bool rightIsAiming;
- protected VRTK_ControllerEvents leftControllerEvents;
- protected VRTK_ControllerEvents rightControllerEvents;
- protected VRTK_InteractGrab leftControllerGrab;
- protected VRTK_InteractGrab rightControllerGrab;
- protected bool leftButtonReleased;
- protected bool rightButtonReleased;
- protected float countDownEndTime;
- /// <summary>
- /// The SetActivationButton method gets the button used to activate a slingshot jump.
- /// </summary>
- /// <returns>Returns the button used for slingshot activation.</returns>
- public virtual VRTK_ControllerEvents.ButtonAlias GetActivationButton()
- {
- return activationButton;
- }
- /// <summary>
- /// The SetActivationButton method sets the button used to activate a slingshot jump.
- /// </summary>
- /// <param name="button">The controller button to use to activate the jump.</param>
- public virtual void SetActivationButton(VRTK_ControllerEvents.ButtonAlias button)
- {
- InitControllerListeners(false);
- activationButton = button;
- InitControllerListeners(true);
- }
- /// <summary>
- /// The GetCancelButton method gets the button used to cancel a slingshot jump.
- /// </summary>
- /// <returns>Returns the button used to cancel a slingshot jump.</returns>
- public virtual VRTK_ControllerEvents.ButtonAlias GetCancelButton()
- {
- return cancelButton;
- }
- /// <summary>
- /// The SetCancelButton method sets the button used to cancel a slingshot jump.
- /// </summary>
- /// <param name="button">The controller button to use to cancel the jump.</param>
- public virtual void SetCancelButton(VRTK_ControllerEvents.ButtonAlias button)
- {
- InitControllerListeners(false);
- cancelButton = button;
- InitControllerListeners(true);
- }
- protected virtual void Awake()
- {
- bodyPhysics = (bodyPhysics != null ? bodyPhysics : FindObjectOfType<VRTK_BodyPhysics>());
- playerClimb = (playerClimb != null ? playerClimb : FindObjectOfType<VRTK_PlayerClimb>());
- VRTK_SDKManager.AttemptAddBehaviourToToggleOnLoadedSetupChange(this);
- }
- protected virtual void OnEnable()
- {
- InitListeners(true);
- playArea = VRTK_DeviceFinder.PlayAreaTransform();
- }
- protected virtual void OnDisable()
- {
- UnAim();
- InitListeners(false);
- }
- protected virtual void OnDestroy()
- {
- VRTK_SDKManager.AttemptRemoveBehaviourToToggleOnLoadedSetupChange(this);
- }
- protected virtual void LeftButtonPressed(object sender, ControllerInteractionEventArgs e)
- {
- // Check for new left aim
- if (!leftIsAiming && !IsClimbing())
- {
- leftIsAiming = true;
- leftStartAimPosition = playArea.InverseTransformPoint(leftControllerEvents.gameObject.transform.position);
- }
- }
- protected virtual void RightButtonPressed(object sender, ControllerInteractionEventArgs e)
- {
- // Check for new right aim
- if (!rightIsAiming && !IsClimbing())
- {
- rightIsAiming = true;
- rightStartAimPosition = playArea.InverseTransformPoint(rightControllerEvents.gameObject.transform.position);
- }
- }
- protected virtual void LeftButtonReleased(object sender, ControllerInteractionEventArgs e)
- {
- // Check for release states
- if (leftIsAiming)
- {
- leftReleasePosition = playArea.InverseTransformPoint(leftControllerEvents.gameObject.transform.position);
- if (!rightButtonReleased)
- {
- countDownEndTime = Time.time + releaseWindowTime;
- }
- leftButtonReleased = true;
- }
- CheckForReset();
- CheckForJump();
- }
- protected virtual void RightButtonReleased(object sender, ControllerInteractionEventArgs e)
- {
- // Check for release states
- if (rightIsAiming)
- {
- rightReleasePosition = playArea.InverseTransformPoint(rightControllerEvents.gameObject.transform.position);
- if (!leftButtonReleased)
- {
- countDownEndTime = Time.time + releaseWindowTime;
- }
- rightButtonReleased = true;
- }
- CheckForReset();
- CheckForJump();
- }
- protected virtual void CancelButtonPressed(object sender, ControllerInteractionEventArgs e)
- {
- UnAim();
- }
- protected virtual void CheckForReset()
- {
- if ((leftButtonReleased || rightButtonReleased) && Time.time > countDownEndTime)
- {
- UnAim();
- }
- }
- protected virtual void CheckForJump()
- {
- if (leftButtonReleased && rightButtonReleased && !bodyPhysics.IsFalling())
- {
- Vector3 leftDir = leftStartAimPosition - leftReleasePosition;
- Vector3 rightDir = rightStartAimPosition - rightReleasePosition;
- Vector3 localJumpDir = leftDir + rightDir;
- Vector3 worldJumpDir = playArea.transform.TransformVector(localJumpDir);
- Vector3 jumpVector = worldJumpDir * velocityMultiplier;
- if (jumpVector.magnitude > velocityMax)
- {
- jumpVector = jumpVector.normalized * velocityMax;
- }
- bodyPhysics.ApplyBodyVelocity(jumpVector, true, true);
- UnAim();
- OnSlingshotJumped();
- }
- }
- protected void OnSlingshotJumped()
- {
- if (SlingshotJumped != null)
- {
- SlingshotJumped(this);
- }
- }
- protected void InitListeners(bool state)
- {
- InitTeleportListener(state);
- InitControllerListeners(state);
- }
- protected void InitTeleportListener(bool state)
- {
- teleporter = (teleporter != null ? teleporter : FindObjectOfType<VRTK_BasicTeleport>());
- if (teleporter != null)
- {
- if (state == true)
- {
- teleporter.Teleporting += new TeleportEventHandler(OnTeleport);
- }
- else
- {
- teleporter.Teleporting -= new TeleportEventHandler(OnTeleport);
- }
- }
- }
- protected void InitControllerListeners(bool state)
- {
- InitControllerListener(state, VRTK_DeviceFinder.GetControllerLeftHand(), ref leftControllerEvents, ref leftControllerGrab, LeftButtonPressed, LeftButtonReleased);
- InitControllerListener(state, VRTK_DeviceFinder.GetControllerRightHand(), ref rightControllerEvents, ref rightControllerGrab, RightButtonPressed, RightButtonReleased);
- }
- protected void InitControllerListener(bool state, GameObject controller, ref VRTK_ControllerEvents events, ref VRTK_InteractGrab grab,
- ControllerInteractionEventHandler triggerPressed, ControllerInteractionEventHandler triggerReleased)
- {
- if (controller != null)
- {
- events = controller.GetComponentInChildren<VRTK_ControllerEvents>();
- grab = controller.GetComponentInChildren<VRTK_InteractGrab>();
- if (events != null)
- {
- if (state == true)
- {
- events.SubscribeToButtonAliasEvent(activationButton, true, triggerPressed);
- events.SubscribeToButtonAliasEvent(activationButton, false, triggerReleased);
- if (cancelButton != VRTK_ControllerEvents.ButtonAlias.Undefined)
- {
- events.SubscribeToButtonAliasEvent(cancelButton, true, CancelButtonPressed);
- }
- }
- else
- {
- events.UnsubscribeToButtonAliasEvent(activationButton, true, triggerPressed);
- events.UnsubscribeToButtonAliasEvent(activationButton, false, triggerReleased);
- if (cancelButton != VRTK_ControllerEvents.ButtonAlias.Undefined)
- {
- events.UnsubscribeToButtonAliasEvent(cancelButton, true, CancelButtonPressed);
- }
- }
- }
- }
- }
- protected void OnTeleport(object sender, DestinationMarkerEventArgs e)
- {
- UnAim();
- }
- protected void UnAim()
- {
- leftIsAiming = false;
- rightIsAiming = false;
- leftButtonReleased = false;
- rightButtonReleased = false;
- }
- protected bool IsClimbing()
- {
- return (playerClimb != null && playerClimb.IsClimbing());
- }
- }
- }
|