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.

190 lines
4.9 KiB

  1. //======= Copyright (c) Valve Corporation, All rights reserved. ===============
  2. //
  3. // Purpose: Throwable that uses physics joints to attach instead of just
  4. // parenting
  5. //
  6. //=============================================================================
  7. using UnityEngine;
  8. using System.Collections.Generic;
  9. namespace Valve.VR.InteractionSystem
  10. {
  11. //-------------------------------------------------------------------------
  12. [RequireComponent( typeof( Interactable ) )]
  13. public class ComplexThrowable : MonoBehaviour
  14. {
  15. public enum AttachMode
  16. {
  17. FixedJoint,
  18. Force,
  19. }
  20. public float attachForce = 800.0f;
  21. public float attachForceDamper = 25.0f;
  22. public AttachMode attachMode = AttachMode.FixedJoint;
  23. [EnumFlags]
  24. public Hand.AttachmentFlags attachmentFlags = 0;
  25. private List<Hand> holdingHands = new List<Hand>();
  26. private List<Rigidbody> holdingBodies = new List<Rigidbody>();
  27. private List<Vector3> holdingPoints = new List<Vector3>();
  28. private List<Rigidbody> rigidBodies = new List<Rigidbody>();
  29. //-------------------------------------------------
  30. void Awake()
  31. {
  32. GetComponentsInChildren<Rigidbody>( rigidBodies );
  33. }
  34. //-------------------------------------------------
  35. void Update()
  36. {
  37. for ( int i = 0; i < holdingHands.Count; i++ )
  38. {
  39. if ( !holdingHands[i].GetStandardInteractionButton() )
  40. {
  41. PhysicsDetach( holdingHands[i] );
  42. }
  43. }
  44. }
  45. //-------------------------------------------------
  46. private void OnHandHoverBegin( Hand hand )
  47. {
  48. if ( holdingHands.IndexOf( hand ) == -1 )
  49. {
  50. if ( hand.controller != null )
  51. {
  52. hand.controller.TriggerHapticPulse( 800 );
  53. }
  54. }
  55. }
  56. //-------------------------------------------------
  57. private void OnHandHoverEnd( Hand hand )
  58. {
  59. if ( holdingHands.IndexOf( hand ) == -1 )
  60. {
  61. if ( hand.controller != null )
  62. {
  63. hand.controller.TriggerHapticPulse( 500 );
  64. }
  65. }
  66. }
  67. //-------------------------------------------------
  68. private void HandHoverUpdate( Hand hand )
  69. {
  70. if ( hand.GetStandardInteractionButtonDown() )
  71. {
  72. PhysicsAttach( hand );
  73. }
  74. }
  75. //-------------------------------------------------
  76. private void PhysicsAttach( Hand hand )
  77. {
  78. PhysicsDetach( hand );
  79. Rigidbody holdingBody = null;
  80. Vector3 holdingPoint = Vector3.zero;
  81. // The hand should grab onto the nearest rigid body
  82. float closestDistance = float.MaxValue;
  83. for ( int i = 0; i < rigidBodies.Count; i++ )
  84. {
  85. float distance = Vector3.Distance( rigidBodies[i].worldCenterOfMass, hand.transform.position );
  86. if ( distance < closestDistance )
  87. {
  88. holdingBody = rigidBodies[i];
  89. closestDistance = distance;
  90. }
  91. }
  92. // Couldn't grab onto a body
  93. if ( holdingBody == null )
  94. return;
  95. // Create a fixed joint from the hand to the holding body
  96. if ( attachMode == AttachMode.FixedJoint )
  97. {
  98. Rigidbody handRigidbody = Util.FindOrAddComponent<Rigidbody>( hand.gameObject );
  99. handRigidbody.isKinematic = true;
  100. FixedJoint handJoint = hand.gameObject.AddComponent<FixedJoint>();
  101. handJoint.connectedBody = holdingBody;
  102. }
  103. // Don't let the hand interact with other things while it's holding us
  104. hand.HoverLock( null );
  105. // Affix this point
  106. Vector3 offset = hand.transform.position - holdingBody.worldCenterOfMass;
  107. offset = Mathf.Min( offset.magnitude, 1.0f ) * offset.normalized;
  108. holdingPoint = holdingBody.transform.InverseTransformPoint( holdingBody.worldCenterOfMass + offset );
  109. hand.AttachObject( this.gameObject, attachmentFlags );
  110. // Update holding list
  111. holdingHands.Add( hand );
  112. holdingBodies.Add( holdingBody );
  113. holdingPoints.Add( holdingPoint );
  114. }
  115. //-------------------------------------------------
  116. private bool PhysicsDetach( Hand hand )
  117. {
  118. int i = holdingHands.IndexOf( hand );
  119. if ( i != -1 )
  120. {
  121. // Detach this object from the hand
  122. holdingHands[i].DetachObject( this.gameObject, false );
  123. // Allow the hand to do other things
  124. holdingHands[i].HoverUnlock( null );
  125. // Delete any existing joints from the hand
  126. if ( attachMode == AttachMode.FixedJoint )
  127. {
  128. Destroy( holdingHands[i].GetComponent<FixedJoint>() );
  129. }
  130. Util.FastRemove( holdingHands, i );
  131. Util.FastRemove( holdingBodies, i );
  132. Util.FastRemove( holdingPoints, i );
  133. return true;
  134. }
  135. return false;
  136. }
  137. //-------------------------------------------------
  138. void FixedUpdate()
  139. {
  140. if ( attachMode == AttachMode.Force )
  141. {
  142. for ( int i = 0; i < holdingHands.Count; i++ )
  143. {
  144. Vector3 targetPoint = holdingBodies[i].transform.TransformPoint( holdingPoints[i] );
  145. Vector3 vdisplacement = holdingHands[i].transform.position - targetPoint;
  146. holdingBodies[i].AddForceAtPosition( attachForce * vdisplacement, targetPoint, ForceMode.Acceleration );
  147. holdingBodies[i].AddForceAtPosition( -attachForceDamper * holdingBodies[i].GetPointVelocity( targetPoint ), targetPoint, ForceMode.Acceleration );
  148. }
  149. }
  150. }
  151. }
  152. }