using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.XR.Interaction.Toolkit; using UnityEngine.XR.Interaction.Toolkit.Interactables; namespace XRMultiplayer.MiniGames { /// /// Represents a mini-game called "Whack-A-Pig" where the player needs to hit pigs with a hammer. /// public class MiniGame_Whack : MiniGameBase { /// /// The time to wait before resetting the hammer's position. /// [SerializeField] float m_HammerResetTime = .25f; /// /// The interactable objects to use for the mini-game. /// readonly Dictionary m_InteractablePoses = new(); /// /// The networked gameplay to use for handling the networked gameplay logic. /// NetworkedWhackAPig m_NetworkedGameplay; /// /// The current score of the mini-game. /// int m_CurrentScore = 0; /// public override void Start() { base.Start(); TryGetComponent(out m_NetworkedGameplay); foreach (var interactable in m_GameInteractables) { if (!m_InteractablePoses.ContainsKey(interactable)) { m_InteractablePoses.Add(interactable, new Pose(interactable.transform.position, interactable.transform.rotation)); interactable.selectExited.AddListener(HammerDropped); } } } /// void OnDestroy() { foreach (var kvp in m_InteractablePoses) { kvp.Key.selectExited.RemoveListener(HammerDropped); } } /// /// Sets up the game by resetting the current score. /// public override void SetupGame() { base.SetupGame(); m_CurrentScore = 0; m_NetworkedGameplay.ResetGame(); } /// /// Starts the game by spawning pigs if the player is the server. /// public override void StartGame() { base.StartGame(); if (m_NetworkedGameplay.IsServer) { m_NetworkedGameplay.SpawnProcessServer(); } } /// /// Finishes the game and ends the networked gameplay. /// /// Whether to submit the score or not. public override void FinishGame(bool submitScore = true) { base.FinishGame(submitScore); m_NetworkedGameplay.EndGame(); } /// /// Called when the hammer is dropped on an interactable object. /// /// The interaction event arguments. void HammerDropped(BaseInteractionEventArgs args) { XRBaseInteractable interactable = (XRBaseInteractable)args.interactableObject; if (m_InteractablePoses.ContainsKey(interactable)) { StartCoroutine(DropHammerAfterTimeRoutine(interactable)); } } /// /// Coroutine that drops the hammer after a specified time and resets the interactable's position. /// /// The interactable object. IEnumerator DropHammerAfterTimeRoutine(XRBaseInteractable interactable) { yield return new WaitForSeconds(m_HammerResetTime); if (!interactable.isSelected) { Rigidbody body = interactable.GetComponent(); bool wasKinematic = body.isKinematic; body.isKinematic = true; interactable.transform.SetPositionAndRotation(m_InteractablePoses[interactable].position, m_InteractablePoses[interactable].rotation); yield return new WaitForFixedUpdate(); body.isKinematic = wasKinematic; foreach (var collider in interactable.colliders) { collider.enabled = true; } } } /// /// Updates the local player's score and submits it to the server. /// /// The point value to add to the score. public void LocalPlayerScored(int pointValue) { m_CurrentScore += pointValue; if (m_CurrentScore < 0) m_CurrentScore = 0; m_MiniGameManager.SubmitScoreServerRpc(m_CurrentScore, XRINetworkPlayer.LocalPlayer.OwnerClientId); } } }