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);
}
}
}