RoguelikeKit/Assets/Common/Scripts/GameController.cs

339 lines
10 KiB
C#

using OctoberStudio.Currency;
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using System.Linq;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace OctoberStudio
{
using OctoberStudio.Audio;
using OctoberStudio.Easing;
using OctoberStudio.Input;
using Save;
using Upgrades;
using Vibration;
public class GameController : MonoBehaviour
{
protected static readonly string MAIN_MENU_MUSIC_NAME = "Main Menu Music";
private static GameController instance;
[SerializeField] protected CurrenciesManager currenciesManager;
public static CurrenciesManager CurrenciesManager => instance.currenciesManager;
[SerializeField] protected UpgradesManager upgradesManager;
public static UpgradesManager UpgradesManager => instance.upgradesManager;
[SerializeField] protected ProjectSettings projectSettings;
public static ProjectSettings ProjectSettings => instance.projectSettings;
public static ISaveManager SaveManager { get; private set; }
public static IAudioManager AudioManager { get; private set; }
public static IVibrationManager VibrationManager { get; private set; }
public static IInputManager InputManager { get; private set; }
public static CurrencySave Gold { get; private set; }
public static CurrencySave TempGold { get; private set; }
public static AudioSource Music { get; private set; }
private static StageSave stageSave;
// Indicates that the main menu is just loaded, and not exited from the game scene
public static bool FirstTimeLoaded { get; private set; }
protected virtual void Awake()
{
if (instance != null)
{
Destroy(this);
FirstTimeLoaded = false;
return;
}
instance = this;
FirstTimeLoaded = true;
currenciesManager.Init();
DontDestroyOnLoad(gameObject);
Application.targetFrameRate = 120;
}
protected virtual void Start()
{
Gold = SaveManager.GetSave<CurrencySave>("gold");
TempGold = SaveManager.GetSave<CurrencySave>("temp_gold");
stageSave = SaveManager.GetSave<StageSave>("Stage");
if (!stageSave.loadedBefore)
{
stageSave.loadedBefore = true;
}
#if UNITY_WEBGL && !UNITY_EDITOR
InputManager.InputAsset.UI.Click.performed += MusicStartWebGL;
#else
EasingManager.DoAfter(0.2f, () => Music = AudioManager.PlayMusic(MAIN_MENU_MUSIC_NAME.GetHashCode()));
#endif
}
#if UNITY_WEBGL && !UNITY_EDITOR
protected virtual void MusicStartWebGL(UnityEngine.InputSystem.InputAction.CallbackContext context)
{
InputManager.InputAsset.UI.Click.performed -= MusicStartWebGL;
Music = AudioManager.PlayMusic(MAIN_MENU_MUSIC_NAME.GetHashCode());
}
#endif
public static void ChangeMusic(string musicName)
{
if (Music != null)
{
var oldMusic = Music;
oldMusic.DoVolume(0, 0.3f).SetOnFinish(() => oldMusic.Stop());
}
Music = AudioManager.PlayMusic(musicName.GetHashCode());
if(Music != null)
{
var volume = Music.volume;
Music.volume = 0;
Music.DoVolume(volume, 0.3f);
}
}
public static void ChangeMusic(SoundContainer music)
{
if (Music != null)
{
var oldMusic = Music;
oldMusic.DoVolume(0, 0.3f).SetOnFinish(() => oldMusic.Stop());
}
Music = music.Play(true);
if (Music != null)
{
var volume = Music.volume;
Music.volume = 0;
Music.DoVolume(volume, 0.3f);
}
}
public static void RegisterInputManager(IInputManager inputManager)
{
InputManager = inputManager;
}
public static void RegisterSaveManager(ISaveManager saveManager)
{
SaveManager = saveManager;
}
public static void RegisterVibrationManager(IVibrationManager vibrationManager)
{
VibrationManager = vibrationManager;
}
public static void RegisterAudioManager(IAudioManager audioManager)
{
AudioManager = audioManager;
}
public static void LoadStage()
{
if(stageSave.ResetStageData) TempGold.Withdraw(TempGold.Amount);
instance.StartCoroutine(StageLoadingCoroutine());
SaveManager.Save(false);
}
public static void LoadMainMenu()
{
Gold.Deposit(TempGold.Amount);
TempGold.Withdraw(TempGold.Amount);
if (instance != null) instance.StartCoroutine(MainMenuLoadingCoroutine());
SaveManager.Save(false);
}
protected static string GetLoadingScreenSceneName()
{
if (ProjectSettings != null && SceneExists(ProjectSettings.LoadingSceneName))
{
return ProjectSettings.LoadingSceneName;
}
else if (SceneExists("Loading Screen"))
{
return "Loading Screen";
}
else
{
Debug.LogWarning("Loading screen scene not found. Please add a loading screen scene to the project settings or ensure it exists in the build settings.");
return null;
}
}
protected static string GetMainMenuSceneName()
{
if (ProjectSettings != null && SceneExists(ProjectSettings.MainMenuSceneName))
{
return ProjectSettings.MainMenuSceneName;
}
else if (SceneExists("Main Menu"))
{
return "Main Menu";
}
else
{
Debug.LogError("Main menu scene not found. Please add a main menu scene to the project settings or ensure it exists in the build settings.");
return null;
}
}
protected static string GetGameSceneName()
{
if (ProjectSettings != null && SceneExists(ProjectSettings.GameSceneName))
{
return ProjectSettings.GameSceneName;
}
else if (SceneExists("Game"))
{
return "Game";
}
else
{
Debug.LogError("Game scene not found. Please add a game scene to the project settings or ensure it exists in the build settings.");
return null;
}
}
protected static IEnumerator StageLoadingCoroutine()
{
var loadingSceneName = GetLoadingScreenSceneName();
var mainMenuSceneName = GetMainMenuSceneName();
var gameSceneName = GetGameSceneName();
if (loadingSceneName != null)
{
yield return LoadAsyncScene(loadingSceneName, LoadSceneMode.Additive);
}
yield return UnloadAsyncScene(mainMenuSceneName);
yield return LoadAsyncScene(gameSceneName, LoadSceneMode.Single);
}
protected static IEnumerator MainMenuLoadingCoroutine()
{
var loadingSceneName = GetLoadingScreenSceneName();
var mainMenuSceneName = GetMainMenuSceneName();
var gameSceneName = GetGameSceneName();
if (loadingSceneName != null)
{
yield return LoadAsyncScene(loadingSceneName, LoadSceneMode.Additive);
}
yield return UnloadAsyncScene(gameSceneName);
yield return LoadAsyncScene(mainMenuSceneName, LoadSceneMode.Single);
if (StageController.Stage.UseCustomMusic)
{
ChangeMusic(MAIN_MENU_MUSIC_NAME);
}
}
protected static bool SceneExists(string sceneName)
{
#if UNITY_EDITOR
return SceneExistsInAssets(sceneName);
#else
return SceneExistsInBuildSettings(sceneName);
#endif
}
protected static bool SceneExistsInBuildSettings(string sceneName)
{
int sceneCount = UnityEngine.SceneManagement.SceneManager.sceneCountInBuildSettings;
for (int i = 0; i < sceneCount; i++)
{
string path = UnityEngine.SceneManagement.SceneUtility.GetScenePathByBuildIndex(i);
string name = System.IO.Path.GetFileNameWithoutExtension(path);
if (name == sceneName)
return true;
}
return false;
}
#if UNITY_EDITOR
public static bool SceneExistsInAssets(string sceneName)
{
string[] guids = AssetDatabase.FindAssets($"t:Scene {sceneName}");
return guids.Any(guid =>
{
string path = AssetDatabase.GUIDToAssetPath(guid);
return System.IO.Path.GetFileNameWithoutExtension(path) == sceneName;
});
}
#endif
protected static IEnumerator UnloadAsyncScene(string sceneName)
{
var asyncLoad = SceneManager.UnloadSceneAsync(sceneName);
asyncLoad.allowSceneActivation = false;
//wait until the asynchronous scene fully loads
while (!asyncLoad.isDone)
{
yield return null;
}
}
protected static IEnumerator LoadAsyncScene(string sceneName, LoadSceneMode loadSceneMode)
{
var asyncLoad = SceneManager.LoadSceneAsync(sceneName, loadSceneMode);
asyncLoad.allowSceneActivation = false;
//wait until the asynchronous scene fully loads
while (!asyncLoad.isDone)
{
//scene has loaded as much as possible,
// the last 10% can't be multi-threaded
if (asyncLoad.progress >= 0.9f)
{
asyncLoad.allowSceneActivation = true;
}
yield return null;
}
}
protected virtual void OnApplicationFocus(bool focus)
{
#if UNITY_WEBGL && !UNITY_EDITOR
if (focus) {
EasingManager.DoAfter(0.1f, () => {
if (!Music.isPlaying)
{
Music = AudioManager.AudioDatabase.Music.Play(true);
}
});
}
#endif
}
}
}