using System; using System.Collections; using Audio; using UnityEngine; using UnityEngine.XR.Interaction.Toolkit; namespace Bow { public class Arrow : XRGrabInteractable { public AudioClipGroup hitSounds; public float speed = 2000.0f; public Transform tip = null; public float maxLifetimeAfterShot = 60f; private bool _inAir = false; private Vector3 _lastPosition = Vector3.zero; private Rigidbody _rigidbody = null; private float _timeToDestroyOn; protected override void Awake() { base.Awake(); _rigidbody = GetComponent(); _timeToDestroyOn = float.MaxValue; } private void FixedUpdate() { if (!_inAir) return; CheckForCollision(); _lastPosition = tip.position; if (_timeToDestroyOn <= Time.time) { Destroy(gameObject); } } private void CheckForCollision() { RaycastHit hit; if (Physics.Linecast(_lastPosition, tip.position, out hit, LayerMask.GetMask("Default"), QueryTriggerInteraction.Ignore)) { hit.collider.gameObject.SendMessage("OnArrowHit", this, SendMessageOptions.DontRequireReceiver); Stop(); hitSounds.Play(); } } private void Stop() { _inAir = false; SetPhysics(false); } public void Release(float pullValue) { _inAir = true; SetPhysics(true); MaskAndFire(pullValue); StartCoroutine(RotateWithVelocity()); _lastPosition = tip.position; } private void SetPhysics(bool usePhysics) { _rigidbody.isKinematic = !usePhysics; _rigidbody.useGravity = usePhysics; } private void MaskAndFire(float power) { colliders[0].enabled = false; interactionLayerMask = 1 << LayerMask.NameToLayer("IgnoreInteraction"); Vector3 force = transform.forward * (power * speed); _rigidbody.AddForce(force); _timeToDestroyOn = Time.time + maxLifetimeAfterShot; } private IEnumerator RotateWithVelocity() { yield return new WaitForFixedUpdate(); while (_inAir) { Quaternion newRotation = Quaternion.LookRotation(_rigidbody.velocity, transform.up); transform.rotation = newRotation; yield return null; } } public new void OnSelectEntered(XRBaseInteractor interactor) { base.OnSelectEntered(interactor); } public new void OnSelectExited(XRBaseInteractor interactor) { base.OnSelectExited(interactor); } public new void OnSelectExiting(XRBaseInteractor interactor) { base.OnSelectExiting(interactor); } protected override void OnDestroy() { base.OnDestroy(); colliders.Clear(); } } }