Throwable.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. //======= Copyright (c) Valve Corporation, All rights reserved. ===============
  2. //
  3. // Purpose: Basic throwable object
  4. //
  5. //=============================================================================
  6. using UnityEngine;
  7. using UnityEngine.Events;
  8. using System.Collections;
  9. namespace Valve.VR.InteractionSystem
  10. {
  11. //-------------------------------------------------------------------------
  12. [RequireComponent( typeof( Interactable ) )]
  13. [RequireComponent( typeof( Rigidbody ) )]
  14. [RequireComponent( typeof(VelocityEstimator))]
  15. public class Throwable : MonoBehaviour
  16. {
  17. [EnumFlags]
  18. [Tooltip( "The flags used to attach this object to the hand." )]
  19. public Hand.AttachmentFlags attachmentFlags = Hand.AttachmentFlags.ParentToHand | Hand.AttachmentFlags.DetachFromOtherHand | Hand.AttachmentFlags.TurnOnKinematic;
  20. [Tooltip("The local point which acts as a positional and rotational offset to use while held")]
  21. public Transform attachmentOffset;
  22. [Tooltip( "How fast must this object be moving to attach due to a trigger hold instead of a trigger press? (-1 to disable)" )]
  23. public float catchingSpeedThreshold = -1;
  24. public ReleaseStyle releaseVelocityStyle = ReleaseStyle.GetFromHand;
  25. [Tooltip("The time offset used when releasing the object with the RawFromHand option")]
  26. public float releaseVelocityTimeOffset = -0.011f;
  27. public float scaleReleaseVelocity = 1.1f;
  28. [Tooltip( "When detaching the object, should it return to its original parent?" )]
  29. public bool restoreOriginalParent = false;
  30. protected VelocityEstimator velocityEstimator;
  31. protected bool attached = false;
  32. protected float attachTime;
  33. protected Vector3 attachPosition;
  34. protected Quaternion attachRotation;
  35. protected Transform attachEaseInTransform;
  36. public UnityEvent onPickUp;
  37. public UnityEvent onDetachFromHand;
  38. public UnityEvent<Hand> onHeldUpdate;
  39. protected RigidbodyInterpolation hadInterpolation = RigidbodyInterpolation.None;
  40. protected new Rigidbody rigidbody;
  41. [HideInInspector]
  42. public Interactable interactable;
  43. //-------------------------------------------------
  44. protected virtual void Awake()
  45. {
  46. velocityEstimator = GetComponent<VelocityEstimator>();
  47. interactable = GetComponent<Interactable>();
  48. rigidbody = GetComponent<Rigidbody>();
  49. rigidbody.maxAngularVelocity = 50.0f;
  50. if(attachmentOffset != null)
  51. {
  52. // remove?
  53. //interactable.handFollowTransform = attachmentOffset;
  54. }
  55. }
  56. //-------------------------------------------------
  57. protected virtual void OnHandHoverBegin( Hand hand )
  58. {
  59. bool showHint = false;
  60. // "Catch" the throwable by holding down the interaction button instead of pressing it.
  61. // Only do this if the throwable is moving faster than the prescribed threshold speed,
  62. // and if it isn't attached to another hand
  63. if ( !attached && catchingSpeedThreshold != -1)
  64. {
  65. float catchingThreshold = catchingSpeedThreshold * SteamVR_Utils.GetLossyScale(Player.instance.trackingOriginTransform);
  66. GrabTypes bestGrabType = hand.GetBestGrabbingType();
  67. if ( bestGrabType != GrabTypes.None )
  68. {
  69. if (rigidbody.velocity.magnitude >= catchingThreshold)
  70. {
  71. hand.AttachObject( gameObject, bestGrabType, attachmentFlags );
  72. showHint = false;
  73. }
  74. }
  75. }
  76. if ( showHint )
  77. {
  78. hand.ShowGrabHint();
  79. }
  80. }
  81. //-------------------------------------------------
  82. protected virtual void OnHandHoverEnd( Hand hand )
  83. {
  84. hand.HideGrabHint();
  85. }
  86. //-------------------------------------------------
  87. protected virtual void HandHoverUpdate( Hand hand )
  88. {
  89. GrabTypes startingGrabType = hand.GetGrabStarting();
  90. if (startingGrabType != GrabTypes.None)
  91. {
  92. hand.AttachObject( gameObject, startingGrabType, attachmentFlags, attachmentOffset );
  93. hand.HideGrabHint();
  94. }
  95. }
  96. //-------------------------------------------------
  97. protected virtual void OnAttachedToHand( Hand hand )
  98. {
  99. //Debug.Log("<b>[SteamVR Interaction]</b> Pickup: " + hand.GetGrabStarting().ToString());
  100. hadInterpolation = this.rigidbody.interpolation;
  101. attached = true;
  102. onPickUp.Invoke();
  103. hand.HoverLock( null );
  104. rigidbody.interpolation = RigidbodyInterpolation.None;
  105. velocityEstimator.BeginEstimatingVelocity();
  106. attachTime = Time.time;
  107. attachPosition = transform.position;
  108. attachRotation = transform.rotation;
  109. }
  110. //-------------------------------------------------
  111. protected virtual void OnDetachedFromHand(Hand hand)
  112. {
  113. attached = false;
  114. onDetachFromHand.Invoke();
  115. hand.HoverUnlock(null);
  116. rigidbody.interpolation = hadInterpolation;
  117. Vector3 velocity;
  118. Vector3 angularVelocity;
  119. GetReleaseVelocities(hand, out velocity, out angularVelocity);
  120. rigidbody.velocity = velocity;
  121. rigidbody.angularVelocity = angularVelocity;
  122. }
  123. public virtual void GetReleaseVelocities(Hand hand, out Vector3 velocity, out Vector3 angularVelocity)
  124. {
  125. if (hand.noSteamVRFallbackCamera && releaseVelocityStyle != ReleaseStyle.NoChange)
  126. releaseVelocityStyle = ReleaseStyle.ShortEstimation; // only type that works with fallback hand is short estimation.
  127. switch (releaseVelocityStyle)
  128. {
  129. case ReleaseStyle.ShortEstimation:
  130. velocityEstimator.FinishEstimatingVelocity();
  131. velocity = velocityEstimator.GetVelocityEstimate();
  132. angularVelocity = velocityEstimator.GetAngularVelocityEstimate();
  133. break;
  134. case ReleaseStyle.AdvancedEstimation:
  135. hand.GetEstimatedPeakVelocities(out velocity, out angularVelocity);
  136. break;
  137. case ReleaseStyle.GetFromHand:
  138. velocity = hand.GetTrackedObjectVelocity(releaseVelocityTimeOffset);
  139. angularVelocity = hand.GetTrackedObjectAngularVelocity(releaseVelocityTimeOffset);
  140. break;
  141. default:
  142. case ReleaseStyle.NoChange:
  143. velocity = rigidbody.velocity;
  144. angularVelocity = rigidbody.angularVelocity;
  145. break;
  146. }
  147. if (releaseVelocityStyle != ReleaseStyle.NoChange)
  148. velocity *= scaleReleaseVelocity;
  149. }
  150. //-------------------------------------------------
  151. protected virtual void HandAttachedUpdate(Hand hand)
  152. {
  153. if (hand.IsGrabEnding(this.gameObject))
  154. {
  155. hand.DetachObject(gameObject, restoreOriginalParent);
  156. // Uncomment to detach ourselves late in the frame.
  157. // This is so that any vehicles the player is attached to
  158. // have a chance to finish updating themselves.
  159. // If we detach now, our position could be behind what it
  160. // will be at the end of the frame, and the object may appear
  161. // to teleport behind the hand when the player releases it.
  162. //StartCoroutine( LateDetach( hand ) );
  163. }
  164. if (onHeldUpdate != null)
  165. onHeldUpdate.Invoke(hand);
  166. }
  167. //-------------------------------------------------
  168. protected virtual IEnumerator LateDetach( Hand hand )
  169. {
  170. yield return new WaitForEndOfFrame();
  171. hand.DetachObject( gameObject, restoreOriginalParent );
  172. }
  173. //-------------------------------------------------
  174. protected virtual void OnHandFocusAcquired( Hand hand )
  175. {
  176. gameObject.SetActive( true );
  177. velocityEstimator.BeginEstimatingVelocity();
  178. }
  179. //-------------------------------------------------
  180. protected virtual void OnHandFocusLost( Hand hand )
  181. {
  182. gameObject.SetActive( false );
  183. velocityEstimator.FinishEstimatingVelocity();
  184. }
  185. }
  186. public enum ReleaseStyle
  187. {
  188. NoChange,
  189. GetFromHand,
  190. ShortEstimation,
  191. AdvancedEstimation,
  192. }
  193. }