using System.Collections; using UnityEngine; using UnityEngine.XR.Interaction.Toolkit; using UnityEngine.XR.Interaction.Toolkit.Interactables; namespace XRMultiplayer.MiniGames { /// /// Base class for mini-games. /// [RequireComponent(typeof(MiniGameManager))] public class MiniGameBase : MonoBehaviour, IMiniGame { /// /// External flag for the game being finished. /// public bool finished { get => m_Finished; set => m_Finished = value; } /// /// Internal flag for the game being finished. /// protected bool m_Finished; /// /// The name of the game. /// public string gameName; /// /// The type of game. /// public enum GameType { Time, Score } /// /// The current game type. /// public GameType currentGameType { get => m_GameType; set => m_GameType = value; } /// /// The game type. /// [SerializeField] GameType m_GameType; /// /// The length of the game. /// [SerializeField] protected float m_GameLength = 90.0f; [SerializeField] protected XRBaseInteractable[] m_GameInteractables; /// /// Manager for the mini-game. /// protected MiniGameManager m_MiniGameManager; /// /// Manager for the interaction. /// protected XRInteractionManager m_InteractionManager; /// /// The current timer for the game. /// protected float m_CurrentTimer; /// /// Flag indicating whether the game ending notification has been sent. /// bool m_GameEndingNotificationSent = false; /// public virtual void Start() { TryGetComponent(out m_MiniGameManager); m_CurrentTimer = m_GameLength; m_InteractionManager = FindFirstObjectByType(); } /// /// Sets up the mini-game. /// public virtual void SetupGame() { if (m_GameType == GameType.Score) { m_CurrentTimer = m_GameLength; } } /// /// Starts the mini-game. /// public virtual void StartGame() { m_GameEndingNotificationSent = false; m_Finished = false; } /// /// Updates the mini-game. /// /// The time since the last frame. public virtual void UpdateGame(float deltaTime) { m_CurrentTimer -= deltaTime; if (m_GameType == GameType.Score) { m_MiniGameManager.m_GameStateText.text = $"Time: {m_CurrentTimer:F0}"; } CheckForGameEnd(); } protected void CheckForGameEnd() { if (m_CurrentTimer <= 3.5f & !m_GameEndingNotificationSent) { m_GameEndingNotificationSent = true; StartCoroutine(CheckForGameEndingRoutine()); } } /// /// Finishes the mini-game. /// /// Flag indicating whether to submit the score. public virtual void FinishGame(bool submitScore = true) { RemoveInteractables(); m_Finished = true; m_CurrentTimer = m_GameLength; } /// /// Coroutine for displaying the game end notification. /// /// An IEnumerator. IEnumerator CheckForGameEndingRoutine() { int seconds = 3; while (seconds > 0) { if (m_MiniGameManager.LocalPlayerInGame) { PlayerHudNotification.Instance.ShowText($"Game Ending In {seconds}"); } yield return new WaitForSeconds(1.0f); seconds--; } if (m_MiniGameManager.LocalPlayerInGame) { PlayerHudNotification.Instance.ShowText($"Game Complete!"); } if (m_MiniGameManager.IsServer && m_MiniGameManager.currentNetworkedGameState == MiniGameManager.GameState.InGame) m_MiniGameManager.StopGameServerRpc(); } /// /// Removes the interactables from the mini-game. /// public virtual void RemoveInteractables() { foreach (IXRInteractable interactable in m_GameInteractables) { m_InteractionManager.CancelInteractableSelection((IXRSelectInteractable)interactable); } } } /// /// Interface for mini-games. /// public interface IMiniGame { /// /// Sets up the mini-game. /// void SetupGame(); /// /// Starts the mini-game. /// void StartGame(); /// /// Updates the mini-game. /// /// The time since the last frame. void UpdateGame(float deltaTime); /// /// Finishes the mini-game. /// /// Flag indicating whether to submit the score. void FinishGame(bool submitScore = true); } }