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);
}
}