123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- //======= Copyright (c) Valve Corporation, All rights reserved. ===============
- //
- // Purpose: Basic throwable object
- //
- //=============================================================================
- using UnityEngine;
- using UnityEngine.Events;
- using System.Collections;
- namespace Valve.VR.InteractionSystem
- {
- //-------------------------------------------------------------------------
- [RequireComponent( typeof( Interactable ) )]
- [RequireComponent( typeof( Rigidbody ) )]
- public class Throwable : MonoBehaviour
- {
- [EnumFlags]
- [Tooltip( "The flags used to attach this object to the hand." )]
- public Hand.AttachmentFlags attachmentFlags = Hand.AttachmentFlags.ParentToHand | Hand.AttachmentFlags.DetachFromOtherHand | Hand.AttachmentFlags.TurnOnKinematic;
- [Tooltip("The local point which acts as a positional and rotational offset to use while held")]
- public Transform attachmentOffset;
- [Tooltip( "How fast must this object be moving to attach due to a trigger hold instead of a trigger press? (-1 to disable)" )]
- public float catchingSpeedThreshold = -1;
- public ReleaseStyle releaseVelocityStyle = ReleaseStyle.GetFromHand;
- [Tooltip("The time offset used when releasing the object with the RawFromHand option")]
- public float releaseVelocityTimeOffset = -0.011f;
- public float scaleReleaseVelocity = 1.1f;
- [Tooltip("The release velocity magnitude representing the end of the scale release velocity curve. (-1 to disable)")]
- public float scaleReleaseVelocityThreshold = -1.0f;
- [Tooltip("Use this curve to ease into the scaled release velocity based on the magnitude of the measured release velocity. This allows greater differentiation between a drop, toss, and throw.")]
- public AnimationCurve scaleReleaseVelocityCurve = AnimationCurve.EaseInOut(0.0f, 0.1f, 1.0f, 1.0f);
- [Tooltip( "When detaching the object, should it return to its original parent?" )]
- public bool restoreOriginalParent = false;
- protected VelocityEstimator velocityEstimator;
- protected bool attached = false;
- protected float attachTime;
- protected Vector3 attachPosition;
- protected Quaternion attachRotation;
- protected Transform attachEaseInTransform;
- public UnityEvent onPickUp;
- public UnityEvent onDetachFromHand;
- public HandEvent onHeldUpdate;
- protected RigidbodyInterpolation hadInterpolation = RigidbodyInterpolation.None;
- protected new Rigidbody rigidbody;
- [HideInInspector]
- public Interactable interactable;
- //-------------------------------------------------
- protected virtual void Awake()
- {
- velocityEstimator = GetComponent<VelocityEstimator>();
- interactable = GetComponent<Interactable>();
- rigidbody = GetComponent<Rigidbody>();
- rigidbody.maxAngularVelocity = 50.0f;
- if(attachmentOffset != null)
- {
- // remove?
- //interactable.handFollowTransform = attachmentOffset;
- }
- }
- //-------------------------------------------------
- protected virtual void OnHandHoverBegin( Hand hand )
- {
- bool showHint = false;
- // "Catch" the throwable by holding down the interaction button instead of pressing it.
- // Only do this if the throwable is moving faster than the prescribed threshold speed,
- // and if it isn't attached to another hand
- if ( !attached && catchingSpeedThreshold != -1)
- {
- float catchingThreshold = catchingSpeedThreshold * SteamVR_Utils.GetLossyScale(Player.instance.trackingOriginTransform);
- GrabTypes bestGrabType = hand.GetBestGrabbingType();
- if ( bestGrabType != GrabTypes.None )
- {
- if (rigidbody.velocity.magnitude >= catchingThreshold)
- {
- hand.AttachObject( gameObject, bestGrabType, attachmentFlags );
- showHint = false;
- }
- }
- }
- if ( showHint )
- {
- hand.ShowGrabHint();
- }
- }
- //-------------------------------------------------
- protected virtual void OnHandHoverEnd( Hand hand )
- {
- hand.HideGrabHint();
- }
- //-------------------------------------------------
- protected virtual void HandHoverUpdate( Hand hand )
- {
- GrabTypes startingGrabType = hand.GetGrabStarting();
- if (startingGrabType != GrabTypes.None)
- {
- hand.AttachObject( gameObject, startingGrabType, attachmentFlags, attachmentOffset );
- hand.HideGrabHint();
- }
- }
- //-------------------------------------------------
- protected virtual void OnAttachedToHand( Hand hand )
- {
- //Debug.Log("<b>[SteamVR Interaction]</b> Pickup: " + hand.GetGrabStarting().ToString());
- hadInterpolation = this.rigidbody.interpolation;
- attached = true;
- onPickUp.Invoke();
- hand.HoverLock( null );
- rigidbody.interpolation = RigidbodyInterpolation.None;
- if (velocityEstimator != null)
- velocityEstimator.BeginEstimatingVelocity();
- attachTime = Time.time;
- attachPosition = transform.position;
- attachRotation = transform.rotation;
- }
- //-------------------------------------------------
- protected virtual void OnDetachedFromHand(Hand hand)
- {
- attached = false;
- onDetachFromHand.Invoke();
- hand.HoverUnlock(null);
- rigidbody.interpolation = hadInterpolation;
- Vector3 velocity;
- Vector3 angularVelocity;
- GetReleaseVelocities(hand, out velocity, out angularVelocity);
- rigidbody.velocity = velocity;
- rigidbody.angularVelocity = angularVelocity;
- }
- public virtual void GetReleaseVelocities(Hand hand, out Vector3 velocity, out Vector3 angularVelocity)
- {
- if (hand.noSteamVRFallbackCamera && releaseVelocityStyle != ReleaseStyle.NoChange)
- releaseVelocityStyle = ReleaseStyle.ShortEstimation; // only type that works with fallback hand is short estimation.
- switch (releaseVelocityStyle)
- {
- case ReleaseStyle.ShortEstimation:
- if (velocityEstimator != null)
- {
- velocityEstimator.FinishEstimatingVelocity();
- velocity = velocityEstimator.GetVelocityEstimate();
- angularVelocity = velocityEstimator.GetAngularVelocityEstimate();
- }
- else
- {
- Debug.LogWarning("[SteamVR Interaction System] Throwable: No Velocity Estimator component on object but release style set to short estimation. Please add one or change the release style.");
- velocity = rigidbody.velocity;
- angularVelocity = rigidbody.angularVelocity;
- }
- break;
- case ReleaseStyle.AdvancedEstimation:
- hand.GetEstimatedPeakVelocities(out velocity, out angularVelocity);
- break;
- case ReleaseStyle.GetFromHand:
- velocity = hand.GetTrackedObjectVelocity(releaseVelocityTimeOffset);
- angularVelocity = hand.GetTrackedObjectAngularVelocity(releaseVelocityTimeOffset);
- break;
- default:
- case ReleaseStyle.NoChange:
- velocity = rigidbody.velocity;
- angularVelocity = rigidbody.angularVelocity;
- break;
- }
- if (releaseVelocityStyle != ReleaseStyle.NoChange)
- {
- float scaleFactor = 1.0f;
- if (scaleReleaseVelocityThreshold > 0)
- {
- scaleFactor = Mathf.Clamp01(scaleReleaseVelocityCurve.Evaluate(velocity.magnitude / scaleReleaseVelocityThreshold));
- }
- velocity *= (scaleFactor * scaleReleaseVelocity);
- }
- }
- //-------------------------------------------------
- protected virtual void HandAttachedUpdate(Hand hand)
- {
- if (hand.IsGrabEnding(this.gameObject))
- {
- hand.DetachObject(gameObject, restoreOriginalParent);
- // Uncomment to detach ourselves late in the frame.
- // This is so that any vehicles the player is attached to
- // have a chance to finish updating themselves.
- // If we detach now, our position could be behind what it
- // will be at the end of the frame, and the object may appear
- // to teleport behind the hand when the player releases it.
- //StartCoroutine( LateDetach( hand ) );
- }
- if (onHeldUpdate != null)
- onHeldUpdate.Invoke(hand);
- }
- //-------------------------------------------------
- protected virtual IEnumerator LateDetach( Hand hand )
- {
- yield return new WaitForEndOfFrame();
- hand.DetachObject( gameObject, restoreOriginalParent );
- }
- //-------------------------------------------------
- protected virtual void OnHandFocusAcquired( Hand hand )
- {
- gameObject.SetActive( true );
- if (velocityEstimator != null)
- velocityEstimator.BeginEstimatingVelocity();
- }
- //-------------------------------------------------
- protected virtual void OnHandFocusLost( Hand hand )
- {
- gameObject.SetActive( false );
- if (velocityEstimator != null)
- velocityEstimator.FinishEstimatingVelocity();
- }
- }
- public enum ReleaseStyle
- {
- NoChange,
- GetFromHand,
- ShortEstimation,
- AdvancedEstimation,
- }
- }
|