using System.Collections;
using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;
namespace XRMultiplayer
{
///
/// This class is responsible for handling the networked despawning of objects based within
/// a trigger volume. It also resets the player controller if they are within the bounds.
/// It also handles the spawning of particles when an object is despawned.
///
public class NetworkObjectDestroyer : NetworkBehaviour
{
///
/// The sub-trigger that triggers the action.
///
[SerializeField] SubTrigger m_SubTrigger;
///
/// The Y offset for the particles that are spawned.
///
[SerializeField] float m_YOffset = .1f;
///
/// The list of scene interactables that cannot be destroyed.
///
[SerializeField] List m_UndestroyableInteractables;
readonly List m_DestroyedInteractables = new();
Pooler m_ParticlePooler;
///
/// Awake is called when the script instance is being loaded.
///
void Awake()
{
if (!TryGetComponent(out m_ParticlePooler))
{
Utils.LogError("NetworkObjectDestroyer requires a Pooler component to be attached to the same GameObject.");
return;
};
m_SubTrigger.OnTriggerAction += Triggered;
}
public override void OnDestroy()
{
base.OnDestroy();
m_SubTrigger.OnTriggerAction -= Triggered;
}
///
/// Event handler for the trigger action.
///
/// The collider that triggered the action.
/// A flag indicating if the collider entered or exited the trigger.
void Triggered(Collider other, bool entered)
{
if (!entered) return;
NetworkBaseInteractable networkBaseInteractable = other.GetComponentInParent();
if (networkBaseInteractable != null)
{
if (m_UndestroyableInteractables.Contains(networkBaseInteractable) || networkBaseInteractable.isInteracting) return;
// This will prevent objects with multiple colliders from being destroyed multiple times.
if (m_DestroyedInteractables.Contains(networkBaseInteractable)) return;
m_DestroyedInteractables.Add(networkBaseInteractable);
Vector3 position = networkBaseInteractable.transform.position + Vector3.up * m_YOffset;
if (!networkBaseInteractable.IsSpawned)
{
Destroy(networkBaseInteractable);
PlayDestroyEffect(position);
// PlayDestroyEffectRpc(position);
}
else if (IsServer)
{
networkBaseInteractable.NetworkObject.Despawn();
PlayDestroyEffectRpc(position);
}
}
else
{
if (other.TryGetComponent(out CharacterResetter playerResetter))
{
PlayDestroyEffectRpc(playerResetter.transform.position);
// PlayDestroyEffectServerRpc(playerResetter.transform.position, NetworkManager.Singleton.LocalClientId);
playerResetter.ResetPlayer();
}
if (other.TryGetComponent(out Projectile projectile))
{
PlayDestroyEffectRpc(projectile.transform.position);
// Destroy(Instantiate(m_DestroyParticles, projectile.transform.position, Quaternion.identity), 1.0f);
projectile.ResetProjectile();
}
}
}
///
/// Plays the destroy effect at the specified position.
///
/// The position at which to play the destroy effect.
void PlayDestroyEffect(Vector3 position)
{
GameObject particleObject = m_ParticlePooler.GetItem();
particleObject.transform.position = position;
StartCoroutine(ReturnParticleToPool(particleObject));
// var particles = particleObject.GetComponent();
// particles.Play();
// var main = particles.main;
// main.stopAction = m_ParticlePooler.ReturnItem(particleObject);
// Destroy(Instantiate(m_DestroyParticles, position, Quaternion.identity), 1.0f);
// PlayDestroyEffectServerRpc(position, NetworkManager.Singleton.LocalClientId);
}
IEnumerator ReturnParticleToPool(GameObject particleObject)
{
yield return new WaitForSeconds(1.0f);
m_ParticlePooler.ReturnItem(particleObject);
}
// ///
// /// Server RPC method for playing the destroy effect on the server.
// ///
// /// The position at which to play the destroy effect.
// /// The client ID of the player triggering the effect.
// [ServerRpc(RequireOwnership = false)]
// void PlayDestroyEffectServerRpc(Vector3 position, ulong clientId)
// {
// PlayDestroyEffectClientRpc(position, clientId);
// }
// ///
// /// Client RPC method for playing the destroy effect on the clients.
// ///
// /// The position at which to play the destroy effect.
// /// The client ID of the player triggering the effect.
// [ClientRpc]
// void PlayDestroyEffectClientRpc(Vector3 position, ulong clientId)
// {
// if (clientId != NetworkManager.Singleton.LocalClientId)
// Destroy(Instantiate(m_DestroyParticles, position, Quaternion.identity), 1.0f);
// }
[Rpc(SendTo.Everyone)]
void PlayDestroyEffectRpc(Vector3 position)
{
PlayDestroyEffect(position);
// if (clientId != NetworkManager.Singleton.LocalClientId)
// Destroy(Instantiate(m_DestroyParticles, position, Quaternion.identity), 1.0f);
}
}
}