/* * author: mark joshwel, sai puay * date: 11/8/2024 * description: game manager singleton for a single source of truth state management */ using System; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.UIElements; using Cursor = UnityEngine.Cursor; /// /// singleton class for managing the game state as a single source of truth /// public class GameManager : MonoBehaviour { /// /// enum for available menus in the game, for use with ShowMenu() /// public enum DisplayState { Game, ScreenMainMenu, ScreenOptionsMenu, OverlayPauseMenu, OverlayCompleteUnderTimeMenu, OverlayFailedOverTimeMenu, UnassociatedState } /// /// singleton pattern: define instance field for accessing the singleton elsewhere /// public static GameManager Instance; /// /// game object for the interaction prompt /// [SerializeField] private GameObject guiInteractionPromptObject; /// /// game object for the heads-up display /// [SerializeField] private GameObject guiHudObject; /// /// the current state of the game /// private DisplayState _state = DisplayState.UnassociatedState; /// /// the visual element object for game ui (hud/prompts/tooltips) /// private VisualElement _ui; /// /// hud ui label for an interaction prompt/tooltip /// private Label _uiLabelInteractionPrompt; /// /// hud ui label for the player's score out of a thousand /// private Label _uiLabelScore; /// /// hud ui label for the speed-run stopwatch /// private Label _uiLabelStopwatch; /// /// property to check if the game is paused based on the current DisplayState /// public bool Paused => _state != DisplayState.Game; /// /// function to set doesn't destroy on load and checks for multiple instances /// /// thrown if a Heads-Up Display game object isn't set in the properties private void Awake() { // check if instance hasn't been set yet if (Instance == null) { // set this instance as the singleton instance Instance = this; // don't destroy this instance on a scene load DontDestroyOnLoad(gameObject); Debug.Log("GameManager: Awake as singleton instance"); } // check if instance is already set and it's not this instance else if (Instance != null && Instance != this) { Debug.Log("GameManager: Awake as non-singleton instance, destroying self"); // destroy the new instance if it's not the singleton instance Destroy(gameObject); } if (guiInteractionPromptObject == null) throw new NullReferenceException("GameManager: guiInteractionPromptObject not set"); if (guiHudObject == null) throw new NullReferenceException("GameManager: guiHudObject not set"); } /// /// called when the game starts, sets state to the main menu /// // /// generic exception it couldn't verify a safe state when starting the game private void Start() { // set to the main menu state SetDisplayState(DisplayState.ScreenMainMenu); // pause the game PauseGameHelper(DisplayState.ScreenMainMenu); } /// /// game run speed run stopwatch logic /// // TODO: implement this (speed-run stopwatch) private void Update() { } /// /// initialise ui elements used by the game[ manager] /// /// > private void OnEnable() { _ui = guiInteractionPromptObject.GetComponent()?.rootVisualElement; _uiLabelInteractionPrompt = _ui.Q