using System.Collections.Generic; using Nox.Platform; using Unity.Profiling; using UnityEngine; namespace Nox.Core { /// /// This is the class that will execute the update cycles for each game state. This should be the only place using Unity's Monobehaviour specific classes /// public class GameStateRunner : MonoBehaviour { private IGameState currentState; private GameState currentStateType; private Dictionary applicationStates; private GameDataState gameDataState; private bool isRunnerUpdated; private bool isUnloading; private IPlatform platform; private ISceneTransition sceneTransition; private GameState pendingStateTransition; private bool isStateTransitioning; private bool waitingForFadeIn; public void Initialize(Dictionary stateLookUp, GameDataState gameDataState, IPlatform selectedPlatform, ISceneTransition sceneTransition) { DontDestroyOnLoad(gameObject); this.platform = selectedPlatform; this.sceneTransition = sceneTransition; applicationStates = stateLookUp; this.gameDataState = gameDataState; ChangeApplicationState(gameDataState.ActiveGameState); } public void FixedUpdate() { if(!currentState.IsGameStateInitialized) { return; } } public void Update() { // Pre-ticks area platform.Tick(); if(waitingForFadeIn) { if(currentState.IsGameStateInitialized) { waitingForFadeIn = false; sceneTransition.FadeIn(() => { isStateTransitioning = false; }); } return; } if(isStateTransitioning) { return; } if(!isRunnerUpdated && currentState.IsGameStateInitialized) { isRunnerUpdated = true; } var nextState = currentStateType; if(isRunnerUpdated || isUnloading) { nextState = currentState.Tick(); if(gameDataState.ActiveGameState != currentStateType) { nextState = gameDataState.ActiveGameState; } } if(nextState != currentStateType) { BeginStateTransition(nextState); } // Ticks area // Post-ticks area } public void LateUpdate() { if(isStateTransitioning || !currentState.IsGameStateInitialized) { return; } currentState.LateTick(); } public void OnDestroy() { currentState.Dispose(); } private void BeginStateTransition(GameState newGameState) { isStateTransitioning = true; pendingStateTransition = newGameState; sceneTransition.FadeOut(() => { ChangeApplicationState(pendingStateTransition); waitingForFadeIn = true; }); } private void ChangeApplicationState(GameState newGameState) { if(currentState != null) { currentState.ExitGameState(); } currentState = applicationStates[newGameState]; currentState.EnterGameState(); currentStateType = newGameState; gameDataState.ChangeGameState(newGameState); isRunnerUpdated = false; Debug.Log($"Entered {newGameState} ApplicationState"); } } }