namespace VRTK.Examples.Archery { using UnityEngine; using System.Collections; public class BowAim : MonoBehaviour { public float powerMultiplier; public float pullMultiplier; public float pullOffset; public float maxPullDistance = 1.1f; public float bowVibration = 0.062f; public float stringVibration = 0.087f; private BowAnimation bowAnimation; private GameObject currentArrow; private BowHandle handle; private VRTK_InteractableObject interact; private VRTK_InteractGrab holdControl; private VRTK_InteractGrab stringControl; private Quaternion releaseRotation; private Quaternion baseRotation; private bool fired; private float fireOffset; private float currentPull; private float previousPull; private AudioSource source; public VRTK_InteractGrab GetPullHand() { return stringControl; } public bool IsHeld() { return interact.IsGrabbed(); } public bool HasArrow() { return currentArrow != null; } public void SetArrow(GameObject arrow) { currentArrow = arrow; PlaySound(); } private void Start() { source = GetComponent(); bowAnimation = GetComponent(); handle = GetComponentInChildren(); interact = GetComponent(); interact.InteractableObjectGrabbed += new InteractableObjectEventHandler(DoObjectGrab); } private void PlaySound() { if (source != null && !source.isPlaying) { source.Play(); } } private void DoObjectGrab(object sender, InteractableObjectEventArgs e) { if (VRTK_DeviceFinder.IsControllerLeftHand(e.interactingObject)) { holdControl = VRTK_DeviceFinder.GetControllerLeftHand().GetComponent(); stringControl = VRTK_DeviceFinder.GetControllerRightHand().GetComponent(); } else { stringControl = VRTK_DeviceFinder.GetControllerLeftHand().GetComponent(); holdControl = VRTK_DeviceFinder.GetControllerRightHand().GetComponent(); } StartCoroutine("GetBaseRotation"); } private IEnumerator GetBaseRotation() { yield return new WaitForEndOfFrame(); baseRotation = transform.localRotation; } private void Update() { if (currentArrow != null && IsHeld()) { AimArrow(); AimBow(); PullString(); if (!stringControl.IsGrabButtonPressed()) { currentArrow.GetComponent().Fired(); fired = true; releaseRotation = transform.localRotation; Release(); } } else if (IsHeld()) { if (fired) { fired = false; fireOffset = Time.time; } if (releaseRotation != baseRotation) { transform.localRotation = Quaternion.Lerp(releaseRotation, baseRotation, (Time.time - fireOffset) * 8); } } if (!IsHeld()) { if (currentArrow != null) { Release(); } } } private void Release() { bowAnimation.SetFrame(0); currentArrow.transform.SetParent(null); Collider[] arrowCols = currentArrow.GetComponentsInChildren(); Collider[] BowCols = GetComponentsInChildren(); foreach (var c in arrowCols) { c.enabled = true; foreach (var C in BowCols) { Physics.IgnoreCollision(c, C); } } currentArrow.GetComponent().isKinematic = false; currentArrow.GetComponent().velocity = currentPull * powerMultiplier * currentArrow.transform.TransformDirection(Vector3.forward); currentArrow.GetComponent().inFlight = true; currentArrow = null; currentPull = 0; ReleaseArrow(); } private void ReleaseArrow() { if (stringControl) { stringControl.ForceRelease(); } } private void AimArrow() { currentArrow.transform.localPosition = Vector3.zero; currentArrow.transform.LookAt(handle.nockSide.position); } private void AimBow() { transform.rotation = Quaternion.LookRotation(holdControl.transform.position - stringControl.transform.position, holdControl.transform.TransformDirection(Vector3.forward)); } private void PullString() { currentPull = Mathf.Clamp((Vector3.Distance(holdControl.transform.position, stringControl.transform.position) - pullOffset) * pullMultiplier, 0, maxPullDistance); bowAnimation.SetFrame(currentPull); if (currentPull.ToString("F2") != previousPull.ToString("F2")) { VRTK_ControllerHaptics.TriggerHapticPulse(VRTK_ControllerReference.GetControllerReference(holdControl.gameObject), bowVibration); VRTK_ControllerHaptics.TriggerHapticPulse(VRTK_ControllerReference.GetControllerReference(stringControl.gameObject), stringVibration); } previousPull = currentPull; } } }