using System.Collections; using Unity.Netcode; using UnityEngine; namespace XRMultiplayer.MiniGames { /// /// A networked slingshot that shoots projectiles. /// [RequireComponent(typeof(SlingshotVisualUpdater))] public class Slingshot : MonoBehaviour { /// /// The projectile prefab to shoot from the slingshot. /// [SerializeField] GameObject m_ProjectilePrefab; /// /// The projectile proxy object to show when the bucket is held. /// [SerializeField] GameObject m_ProjectileProxyObject; /// /// The bucket interactable to use for setting the power of the slingshot. /// [SerializeField] NetworkPhysicsInteractable m_BucketInteractable; /// /// The time to wait before resetting the proxy object. /// [SerializeField] float m_ResetTime = 1.0f; /// /// The colliders to ignore when shooting the projectile. /// [SerializeField] Collider[] m_CollidersToIgnore; /// /// The slingshot visual updater to use for updating the slingshot visuals. /// SlingshotVisualUpdater m_SlingshotVisualUpdater; /// /// The slingshot mini game to use for handling the mini game logic. /// MiniGame_Slingshot m_MiniGame; /// /// Called when the script instance is being loaded. /// private void Start() { TryGetComponent(out m_SlingshotVisualUpdater); m_MiniGame = GetComponentInParent(); } /// /// Called when the bucket's held state changes. /// /// The previous held state. /// The current held state. public void OnBucketHeldChanged(bool current) { if (!current) { ShootProjectile(); } else { if (m_BucketInteractable.IsOwner) { m_SlingshotVisualUpdater.trajectoryLineRenderer.enabled = true; } } } /// /// Shoots a projectile from the slingshot. /// private void ShootProjectile() { m_ProjectileProxyObject.SetActive(false); SlingshotProjectile projectile = Instantiate(m_ProjectilePrefab, m_BucketInteractable.transform.position, Quaternion.identity).GetComponent(); XRINetworkGameManager.Instance.GetPlayerByID(m_BucketInteractable.OwnerClientId, out XRINetworkPlayer player); projectile.LaunchProjectile(m_SlingshotVisualUpdater.GetShotForce(), player.IsLocalPlayer, player.playerColor); foreach (var collider in m_CollidersToIgnore) { Physics.IgnoreCollision(projectile.GetComponent(), collider); } if (m_BucketInteractable.IsOwner) { projectile.localPlayerHitTarget += OnLocalPlayerHitTarget; m_SlingshotVisualUpdater.ResetBucketPosition(); ResetProxyObjectServerRpc(); m_SlingshotVisualUpdater.trajectoryLineRenderer.enabled = false; } } /// /// Resets the proxy object on the server. /// [ServerRpc(RequireOwnership = false)] private void ResetProxyObjectServerRpc() { ResetProxyObjectClientRpc(); } /// /// Resets the proxy object on the clients. /// [ClientRpc] private void ResetProxyObjectClientRpc() { StartCoroutine(ResetProxyAfterTime()); } /// /// Resets the proxy object after a specified time. /// /// An enumerator to control the coroutine. private IEnumerator ResetProxyAfterTime() { yield return new WaitForSeconds(m_ResetTime); m_ProjectileProxyObject.SetActive(true); } /// /// Called when the local player hits a target with the projectile. /// /// The projectile that hit the target. /// The value of the target hit. private void OnLocalPlayerHitTarget(SlingshotProjectile projectile, int targetValue) { projectile.localPlayerHitTarget -= OnLocalPlayerHitTarget; m_MiniGame.LocalPlayerHitTarget(targetValue); } } }