using System.Collections.Generic; using Unity.Netcode; using UnityEngine; using XRMultiplayer; /// /// Networked Projectile Launcher. /// public class NetworkProjectileLauncher : NetworkBehaviour { [SerializeField] [Tooltip("The point that the project is created")] Transform m_StartPoint = null; // [SerializeField] // [Tooltip("The projectile that's created")] // GameObject m_ProjectilePrefab = null; [SerializeField] [Tooltip("The speed at which the projectile is launched")] float m_LaunchSpeed = 1000f; [SerializeField] [Tooltip("The speed at which the projectile is launched")] int m_MaxProjectilesAllowed = 15; readonly List m_ProjectileQueue = new(); [Header("Audio")] [SerializeField] AudioSource m_AudioSource; [SerializeField] AudioClip m_AudioClip; /// /// Networked Color. This value gets set when ownership is gained. /// readonly NetworkVariable m_ProjectileColor = new(default, NetworkVariableReadPermission.Everyone, NetworkVariableWritePermission.Owner); /// /// Backup color to use for the local player if ownership has not been established when firing the launcher. /// /// /// This will only be used if the player picks up the launcher and fires immediately. /// This Color is not synchronized over the network and will result in inconsistency between players when used. /// Color m_BackupColor; PoolerProjectiles m_ProjectilePooler; void Awake() { m_ProjectilePooler = FindFirstObjectByType(); } /// public override void OnNetworkSpawn() { base.OnNetworkSpawn(); if (IsOwner) { m_ProjectileColor.Value = XRINetworkGameManager.LocalPlayerColor.Value; } } /// /// Synchronize the firing of the projectile. /// /// public void FireLauncher(bool activate) { if (activate) { Color fireColor = m_BackupColor; if (m_ProjectileColor.Value != default) { fireColor = m_ProjectileColor.Value; } GameObject newObject = m_ProjectilePooler.GetItem(); if (!newObject.TryGetComponent(out Projectile projectile)) { Utils.Log("Projectile component not found on projectile object.", 1); return; } projectile.transform.SetPositionAndRotation(m_StartPoint.position, m_StartPoint.rotation); projectile.Setup(IsOwner, fireColor, OnProjectileDestroy); m_AudioSource.PlayOneShot(m_AudioClip); if (newObject.TryGetComponent(out Rigidbody rigidBody)) { rigidBody.isKinematic = true; rigidBody.isKinematic = false; Vector3 force = m_StartPoint.forward * m_LaunchSpeed; rigidBody.AddForce(force); } m_ProjectileQueue.Add(projectile); if (m_ProjectileQueue.Count > m_MaxProjectilesAllowed) { m_ProjectileQueue[0].ResetProjectile(); } } } void OnProjectileDestroy(Projectile projectile) { if (m_ProjectileQueue.Contains(projectile)) { m_ProjectileQueue.Remove(projectile); } m_ProjectilePooler.ReturnItem(projectile.gameObject); } /// public override void OnGainedOwnership() { base.OnGainedOwnership(); if (IsOwner) { m_ProjectileColor.Value = XRINetworkGameManager.LocalPlayerColor.Value; } } }