using System; using System.Collections; using UnityEngine; namespace XRMultiplayer { /// /// Represents a projectile in the game. /// public class Projectile : MonoBehaviour { /// /// The trail renderer for the projectile. /// [SerializeField] protected TrailRenderer m_TrailRenderer; [SerializeField] protected float m_Lifetime = 10.0f; /// /// The previous position of the projectile. /// Vector3 m_PrevPos = Vector3.zero; /// /// The raycast hit for the projectile. /// RaycastHit m_Hit; /// /// Indicates whether the projectile has hit a target. /// bool m_HasHitTarget = false; /// /// Indicates whether the projectile belongs to the local player. /// bool m_LocalPlayerProjectile; Action m_OnReturnToPool; Rigidbody m_Rigidybody; /// /// Sets up the projectile with the specified parameters. /// /// Indicates whether the projectile belongs to the local player. /// The color of the player. public void Setup(bool localPlayer, Color playerColor, Action returnToPoolAction = null) { if (m_Rigidybody == null) { TryGetComponent(out m_Rigidybody); } m_LocalPlayerProjectile = localPlayer; m_TrailRenderer.startColor = playerColor; m_TrailRenderer.endColor = playerColor; m_TrailRenderer.Clear(); m_PrevPos = transform.position; if (returnToPoolAction != null) { m_OnReturnToPool = returnToPoolAction; StartCoroutine(ResetProjectileAfterTime()); } } IEnumerator ResetProjectileAfterTime() { yield return new WaitForSeconds(m_Lifetime); ResetProjectile(); } /// private void FixedUpdate() { if (!m_LocalPlayerProjectile || m_HasHitTarget) return; if (Physics.Linecast(m_PrevPos, transform.position, out m_Hit)) { if (m_Hit.transform.CompareTag("Target")) { HitTarget(m_Hit.transform.GetComponentInParent()); } CheckForInteractableHit(m_Hit.transform); } m_PrevPos = transform.position; } /// void OnTriggerEnter(Collider other) { if (other.CompareTag("Target")) { HitTarget(other.GetComponentInParent()); } } void OnCollisionEnter(Collision collision) { if (!m_LocalPlayerProjectile) return; CheckForInteractableHit(collision.transform); } void CheckForInteractableHit(Transform t) { NetworkPhysicsInteractable networkPhysicsInteractable = t.GetComponentInParent(); if (networkPhysicsInteractable != null) { networkPhysicsInteractable.RequestOwnership(); } } /// /// Called when the projectile hits a target. /// /// The target that was hit. protected virtual void HitTarget(Target target) { target.TargetHitLocal(); m_HasHitTarget = true; } public void ResetProjectile() { StopAllCoroutines(); m_OnReturnToPool?.Invoke(this); } } }