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.

183 lines
5.9 KiB

  1. namespace VRTK.Examples.Archery
  2. {
  3. using UnityEngine;
  4. using System.Collections;
  5. public class BowAim : MonoBehaviour
  6. {
  7. public float powerMultiplier;
  8. public float pullMultiplier;
  9. public float pullOffset;
  10. public float maxPullDistance = 1.1f;
  11. public float bowVibration = 0.062f;
  12. public float stringVibration = 0.087f;
  13. private BowAnimation bowAnimation;
  14. private GameObject currentArrow;
  15. private BowHandle handle;
  16. private VRTK_InteractableObject interact;
  17. private VRTK_InteractGrab holdControl;
  18. private VRTK_InteractGrab stringControl;
  19. private Quaternion releaseRotation;
  20. private Quaternion baseRotation;
  21. private bool fired;
  22. private float fireOffset;
  23. private float currentPull;
  24. private float previousPull;
  25. private AudioSource source;
  26. public VRTK_InteractGrab GetPullHand()
  27. {
  28. return stringControl;
  29. }
  30. public bool IsHeld()
  31. {
  32. return interact.IsGrabbed();
  33. }
  34. public bool HasArrow()
  35. {
  36. return currentArrow != null;
  37. }
  38. public void SetArrow(GameObject arrow)
  39. {
  40. currentArrow = arrow;
  41. PlaySound();
  42. }
  43. private void Start()
  44. {
  45. source = GetComponent<AudioSource>();
  46. bowAnimation = GetComponent<BowAnimation>();
  47. handle = GetComponentInChildren<BowHandle>();
  48. interact = GetComponent<VRTK_InteractableObject>();
  49. interact.InteractableObjectGrabbed += new InteractableObjectEventHandler(DoObjectGrab);
  50. }
  51. private void PlaySound()
  52. {
  53. if (source != null && !source.isPlaying)
  54. {
  55. source.Play();
  56. }
  57. }
  58. private void DoObjectGrab(object sender, InteractableObjectEventArgs e)
  59. {
  60. if (VRTK_DeviceFinder.IsControllerLeftHand(e.interactingObject))
  61. {
  62. holdControl = VRTK_DeviceFinder.GetControllerLeftHand().GetComponent<VRTK_InteractGrab>();
  63. stringControl = VRTK_DeviceFinder.GetControllerRightHand().GetComponent<VRTK_InteractGrab>();
  64. }
  65. else
  66. {
  67. stringControl = VRTK_DeviceFinder.GetControllerLeftHand().GetComponent<VRTK_InteractGrab>();
  68. holdControl = VRTK_DeviceFinder.GetControllerRightHand().GetComponent<VRTK_InteractGrab>();
  69. }
  70. StartCoroutine("GetBaseRotation");
  71. }
  72. private IEnumerator GetBaseRotation()
  73. {
  74. yield return new WaitForEndOfFrame();
  75. baseRotation = transform.localRotation;
  76. }
  77. private void Update()
  78. {
  79. if (currentArrow != null && IsHeld())
  80. {
  81. AimArrow();
  82. AimBow();
  83. PullString();
  84. if (!stringControl.IsGrabButtonPressed())
  85. {
  86. currentArrow.GetComponent<Arrow>().Fired();
  87. fired = true;
  88. releaseRotation = transform.localRotation;
  89. Release();
  90. }
  91. }
  92. else if (IsHeld())
  93. {
  94. if (fired)
  95. {
  96. fired = false;
  97. fireOffset = Time.time;
  98. }
  99. if (releaseRotation != baseRotation)
  100. {
  101. transform.localRotation = Quaternion.Lerp(releaseRotation, baseRotation, (Time.time - fireOffset) * 8);
  102. }
  103. }
  104. if (!IsHeld())
  105. {
  106. if (currentArrow != null)
  107. {
  108. Release();
  109. }
  110. }
  111. }
  112. private void Release()
  113. {
  114. bowAnimation.SetFrame(0);
  115. currentArrow.transform.SetParent(null);
  116. Collider[] arrowCols = currentArrow.GetComponentsInChildren<Collider>();
  117. Collider[] BowCols = GetComponentsInChildren<Collider>();
  118. foreach (var c in arrowCols)
  119. {
  120. c.enabled = true;
  121. foreach (var C in BowCols)
  122. {
  123. Physics.IgnoreCollision(c, C);
  124. }
  125. }
  126. currentArrow.GetComponent<Rigidbody>().isKinematic = false;
  127. currentArrow.GetComponent<Rigidbody>().velocity = currentPull * powerMultiplier * currentArrow.transform.TransformDirection(Vector3.forward);
  128. currentArrow.GetComponent<Arrow>().inFlight = true;
  129. currentArrow = null;
  130. currentPull = 0;
  131. ReleaseArrow();
  132. }
  133. private void ReleaseArrow()
  134. {
  135. if (stringControl)
  136. {
  137. stringControl.ForceRelease();
  138. }
  139. }
  140. private void AimArrow()
  141. {
  142. currentArrow.transform.localPosition = Vector3.zero;
  143. currentArrow.transform.LookAt(handle.nockSide.position);
  144. }
  145. private void AimBow()
  146. {
  147. transform.rotation = Quaternion.LookRotation(holdControl.transform.position - stringControl.transform.position, holdControl.transform.TransformDirection(Vector3.forward));
  148. }
  149. private void PullString()
  150. {
  151. currentPull = Mathf.Clamp((Vector3.Distance(holdControl.transform.position, stringControl.transform.position) - pullOffset) * pullMultiplier, 0, maxPullDistance);
  152. bowAnimation.SetFrame(currentPull);
  153. if (currentPull.ToString("F2") != previousPull.ToString("F2"))
  154. {
  155. VRTK_ControllerHaptics.TriggerHapticPulse(VRTK_ControllerReference.GetControllerReference(holdControl.gameObject), bowVibration);
  156. VRTK_ControllerHaptics.TriggerHapticPulse(VRTK_ControllerReference.GetControllerReference(stringControl.gameObject), stringVibration);
  157. }
  158. previousPull = currentPull;
  159. }
  160. }
  161. }