123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- //======= Copyright (c) Valve Corporation, All rights reserved. ===============
- //
- // Purpose: Throwable that uses physics joints to attach instead of just
- // parenting
- //
- //=============================================================================
- using UnityEngine;
- using System.Collections.Generic;
- namespace Valve.VR.InteractionSystem
- {
- //-------------------------------------------------------------------------
- [RequireComponent( typeof( Interactable ) )]
- public class ComplexThrowable : MonoBehaviour
- {
- public enum AttachMode
- {
- FixedJoint,
- Force,
- }
- public float attachForce = 800.0f;
- public float attachForceDamper = 25.0f;
- public AttachMode attachMode = AttachMode.FixedJoint;
- [EnumFlags]
- public Hand.AttachmentFlags attachmentFlags = 0;
- private List<Hand> holdingHands = new List<Hand>();
- private List<Rigidbody> holdingBodies = new List<Rigidbody>();
- private List<Vector3> holdingPoints = new List<Vector3>();
- private List<Rigidbody> rigidBodies = new List<Rigidbody>();
- //-------------------------------------------------
- void Awake()
- {
- GetComponentsInChildren<Rigidbody>( rigidBodies );
- }
- //-------------------------------------------------
- void Update()
- {
- for ( int i = 0; i < holdingHands.Count; i++ )
- {
- if (holdingHands[i].IsGrabEnding(this.gameObject))
- {
- PhysicsDetach( holdingHands[i] );
- }
- }
- }
- //-------------------------------------------------
- private void OnHandHoverBegin( Hand hand )
- {
- if ( holdingHands.IndexOf( hand ) == -1 )
- {
- if ( hand.isActive )
- {
- hand.TriggerHapticPulse( 800 );
- }
- }
- }
- //-------------------------------------------------
- private void OnHandHoverEnd( Hand hand )
- {
- if ( holdingHands.IndexOf( hand ) == -1 )
- {
- if (hand.isActive)
- {
- hand.TriggerHapticPulse( 500 );
- }
- }
- }
- //-------------------------------------------------
- private void HandHoverUpdate( Hand hand )
- {
- GrabTypes startingGrabType = hand.GetGrabStarting();
- if (startingGrabType != GrabTypes.None)
- {
- PhysicsAttach( hand, startingGrabType );
- }
- }
- //-------------------------------------------------
- private void PhysicsAttach( Hand hand, GrabTypes startingGrabType )
- {
- PhysicsDetach( hand );
- Rigidbody holdingBody = null;
- Vector3 holdingPoint = Vector3.zero;
- // The hand should grab onto the nearest rigid body
- float closestDistance = float.MaxValue;
- for ( int i = 0; i < rigidBodies.Count; i++ )
- {
- float distance = Vector3.Distance( rigidBodies[i].worldCenterOfMass, hand.transform.position );
- if ( distance < closestDistance )
- {
- holdingBody = rigidBodies[i];
- closestDistance = distance;
- }
- }
- // Couldn't grab onto a body
- if ( holdingBody == null )
- return;
- // Create a fixed joint from the hand to the holding body
- if ( attachMode == AttachMode.FixedJoint )
- {
- Rigidbody handRigidbody = Util.FindOrAddComponent<Rigidbody>( hand.gameObject );
- handRigidbody.isKinematic = true;
- FixedJoint handJoint = hand.gameObject.AddComponent<FixedJoint>();
- handJoint.connectedBody = holdingBody;
- }
- // Don't let the hand interact with other things while it's holding us
- hand.HoverLock( null );
- // Affix this point
- Vector3 offset = hand.transform.position - holdingBody.worldCenterOfMass;
- offset = Mathf.Min( offset.magnitude, 1.0f ) * offset.normalized;
- holdingPoint = holdingBody.transform.InverseTransformPoint( holdingBody.worldCenterOfMass + offset );
- hand.AttachObject( this.gameObject, startingGrabType, attachmentFlags );
- // Update holding list
- holdingHands.Add( hand );
- holdingBodies.Add( holdingBody );
- holdingPoints.Add( holdingPoint );
- }
- //-------------------------------------------------
- private bool PhysicsDetach( Hand hand )
- {
- int i = holdingHands.IndexOf( hand );
- if ( i != -1 )
- {
- // Detach this object from the hand
- holdingHands[i].DetachObject( this.gameObject, false );
- // Allow the hand to do other things
- holdingHands[i].HoverUnlock( null );
- // Delete any existing joints from the hand
- if ( attachMode == AttachMode.FixedJoint )
- {
- Destroy( holdingHands[i].GetComponent<FixedJoint>() );
- }
- Util.FastRemove( holdingHands, i );
- Util.FastRemove( holdingBodies, i );
- Util.FastRemove( holdingPoints, i );
- return true;
- }
- return false;
- }
- //-------------------------------------------------
- void FixedUpdate()
- {
- if ( attachMode == AttachMode.Force )
- {
- for ( int i = 0; i < holdingHands.Count; i++ )
- {
- Vector3 targetPoint = holdingBodies[i].transform.TransformPoint( holdingPoints[i] );
- Vector3 vdisplacement = holdingHands[i].transform.position - targetPoint;
- holdingBodies[i].AddForceAtPosition( attachForce * vdisplacement, targetPoint, ForceMode.Acceleration );
- holdingBodies[i].AddForceAtPosition( -attachForceDamper * holdingBodies[i].GetPointVelocity( targetPoint ), targetPoint, ForceMode.Acceleration );
- }
- }
- }
- }
- }
|