using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.Video; using UnityEngine.SceneManagement; public enum GameMode { SinglePlayer, LocalMultiplayer, CashSystem } public class GameManager : MonoBehaviour { //Game Mode public GameMode currentGameMode; //Single Player public GameObject inScenePlayer; //Local Multiplayer public GameObject playerPrefab; public GameObject homeScreen; public GameObject splashScreen; public int numberOfPlayers; public Transform spawnRingCenter; public float spawnRingRadius; //Spawned Players private bool isPaused; public static GameManager Instance; public ModeSelection modeSelection; public WaitingSceneManager waitingSceneManager; private int enemiesDefeated = 0; public AudioSource audioSource; public AudioSource sfxSource; ///this should carry the value of the selected players from the modeselection script and make it available in another scene(game scene) public Dictionary selectedPlayerDevice; [SerializeField] private Slider progressBar; public RawImage rawImage; public VideoPlayer videoPlayer; private bool isVideoFinished = false; public event Action SplashSequenceCompleted; public GameObject loadingUI; // Reference to the Loading UI Canvas // private GameSettings gameSettings; // void OnEnable(){ // //If Key is present, then load // if (PlayerPrefs.HasKey(GameSettingsKey)) // { // gameSettings = LoadGameSettings(); //Load // } // // else{ // // DefaultSettings(); //Set Volume and Controls Settings // // // SaveGameSettings(); // // } // } private GameSettings gameSettings; void LoadAudioSetings(){ if (PlayerPrefs.HasKey(GameSettingsKey)) { gameSettings = LoadGameSettings(); //Load } else { gameSettings = new GameSettings(); // Create default settings if none exist } } private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); return; // prevent duplicate initialization } Instance = this; DontDestroyOnLoad(gameObject); if (sfxSource == null) { sfxSource = gameObject.AddComponent(); sfxSource.playOnAwake = false; } if (selectedPlayerDevice == null) selectedPlayerDevice = new Dictionary(); audioSource = GetComponent(); } void Start() { isPaused = false; //SetupBasedOnGameState(); //SetupUI(); // Set the video player's target texture to the raw image's texture videoPlayer.targetTexture = new RenderTexture(Screen.width, Screen.height, 24); rawImage.texture = videoPlayer.targetTexture; // Record when splash started for minimum duration check splashStartTime = Time.realtimeSinceStartup; // Subscribe to the videoPlayer's completion event videoPlayer.loopPointReached += OnVideoFinished; } //BG Music public void PlayBackgroundMusic() { //audio play LoadAudioSetings(); Debug.Log($"BG MUSIC PLAYING {gameSettings.GameplayVolume_value}"); audioSource.volume = gameSettings.GameplayVolume_value; audioSource.Play(); } //UI click public void PlaySound(AudioClip sfxClip) { if (sfxClip == null) { Debug.LogWarning("Attempted to play null audio clip"); return; } if (sfxSource == null) { Debug.LogWarning("sfxSource is null, attempting to recreate"); sfxSource = gameObject.AddComponent(); sfxSource.playOnAwake = false; } LoadAudioSetings(); sfxSource.clip = sfxClip; sfxSource.volume = gameSettings != null ? gameSettings.UIVolume_value : 1f; sfxSource.Play(); } public void ActivateHomeScreen() { // Perform actions to activate the home screen here homeScreen.SetActive(true); } // Minimum time (seconds) the splash should display before transitioning private float splashStartTime; private const float MIN_SPLASH_DURATION = 2.0f; // At least 2 seconds // Method called when the video finishes playing private void OnVideoFinished(VideoPlayer player) { // Set the flag to true to indicate that the video has finished playing if (isVideoFinished) { return; } // Check if the video actually played for a reasonable duration float timeSinceSplashStart = Time.realtimeSinceStartup - splashStartTime; double videoLength = player != null && player.length > 0 ? player.length : 0; Debug.Log($"[GameManager] loopPointReached triggered. Time since start: {timeSinceSplashStart:F2}s, Video length: {videoLength:F2}s, IsPlaying: {player?.isPlaying}"); // If the event fired too quickly (video didn't actually play), wait for it if (timeSinceSplashStart < MIN_SPLASH_DURATION && timeSinceSplashStart < videoLength * 0.5f) { Debug.LogWarning($"[GameManager] Video finished too quickly ({timeSinceSplashStart:F2}s). Starting fallback wait..."); StartCoroutine(WaitForMinimumSplashDuration()); return; } isVideoFinished = true; Debug.Log("[GameManager] Splash video finished. Starting scene load coroutine to avoid blocking main thread."); // Start coroutine to avoid blocking the VideoPlayer callback thread StartCoroutine(LoadMenuAfterSplash()); } private System.Collections.IEnumerator WaitForMinimumSplashDuration() { // Wait until minimum duration has passed float remainingTime = MIN_SPLASH_DURATION - (Time.realtimeSinceStartup - splashStartTime); if (remainingTime > 0) { Debug.Log($"[GameManager] Waiting {remainingTime:F2}s for minimum splash duration..."); yield return new WaitForSeconds(remainingTime); } if (!isVideoFinished) { isVideoFinished = true; Debug.Log("[GameManager] Minimum splash duration reached. Starting scene load."); StartCoroutine(LoadMenuAfterSplash()); } } private System.Collections.IEnumerator LoadMenuAfterSplash() { ShowLoadingUI(); // Invoke the event - GameInitialize will handle scene loading if subscribed // This prevents duplicate scene load attempts bool hasSubscribers = SplashSequenceCompleted != null; SplashSequenceCompleted?.Invoke(); // Wait one frame to ensure UI updates before potentially heavy operations yield return null; // Only load scene directly if no subscribers handled it // (GameInitialize subscribes when forceMenuDuringDevelopment is true) if (!hasSubscribers) { const string forcedScene = "MenuScene"; Debug.Log("[GameManager] Loading '" + forcedScene + "' via LoadingScreen (no external subscribers)."); LoadSceneWithLoading(forcedScene); } else { Debug.Log("[GameManager] Splash finished - scene loading handled by subscriber."); } } private void ActivateLoadingBar() { // Show the loading bar or perform any other loading-related actions here //SceneManager.LoadScene("MenuScene", LoadSceneMode.Single); SceneManager.sceneLoaded += OnSceneLoaded; } public void OnSceneLoaded(Scene scene, LoadSceneMode mode){ SceneManager.sceneLoaded -= OnSceneLoaded; // Unregister event handler if (scene.name != "MenuScene") { return; } // Debug.Log("XT Loading Bar"); //Find GameObject with name "UI" GameObject uiObject = GameObject.Find("UI"); if (uiObject != null){ /*foreach (Transform child in uiObject.transform){ if ((child.name != "ModeSelection")){ child.gameObject.SetActive(false); } }*/ //Check if Announcements have been shown or not, if shown, go to Loading_Screen UI, but if not yet shown, then go to Announcements UI // Check if the "announcement" key exists in PlayerPrefs // Get the value of the "announcement" key string announcementValue = PlayerPrefs.GetString("announcementStatus"); // Check if the value is "0", Announcements have not happened if (announcementValue == "0"){ GameObject announcements_to_show = uiObject.transform.Find("Announcements")?.gameObject; if (announcements_to_show != null){ announcements_to_show.SetActive(true); //When the Menu scene is activated, show this UI }else{ Debug.Log("No Announcements screen"); } } else{ //Announcements already happened //LoadingScreen loadingscript = GetComponent(); //ActivateHomeScreen(); //GameManager.Instance.gameObject.GetComponent().UI_to_show_AfterLoading(2, "Home"); } } else{ Debug.LogError("UI GameObject not found in MenuScene!"); } } public void IncrementEnemiesDefeated() { enemiesDefeated++; } public int GetEnemiesDefeated() { return enemiesDefeated; } void SetupLocalMultiplayer() { if (inScenePlayer == true) { Destroy(inScenePlayer); } } public void HideLoadingUI() { loadingUI.SetActive(false); } public bool HasSplashFinished => isVideoFinished; public void ShowLoadingUI() { if (loadingUI == null) { if (gameObject.transform.childCount > 0) { loadingUI = gameObject.transform.GetChild(0).gameObject; } else { Debug.LogError("ShowLoadingUI: No child GameObject found. Please ensure the hierarchy is set up correctly."); return; } } loadingUI.SetActive(true); } public void LoadSceneWithLoading(string sceneName) { if (string.IsNullOrEmpty(sceneName)) { Debug.LogError("LoadSceneWithLoading: sceneName is null or empty"); return; } var loadingScreen = GetComponentInChildren(true); if (loadingScreen != null) { loadingScreen.UI_to_show_AfterLoading(1, sceneName); ShowLoadingUI(); } else { Debug.LogWarning("LoadSceneWithLoading: LoadingScreen component not found. Falling back to direct scene load."); SceneManager.LoadScene(sceneName, LoadSceneMode.Single); } } //Saving and Loading Game Settings #region private const string GameSettingsKey = "GameSettings"; public static void SaveGameSettings(GameSettings settings){ string json = JsonUtility.ToJson(settings); PlayerPrefs.SetString(GameSettingsKey, json); PlayerPrefs.Save(); } public static GameSettings LoadGameSettings(){ if (PlayerPrefs.HasKey(GameSettingsKey)) { string json = PlayerPrefs.GetString(GameSettingsKey); return JsonUtility.FromJson(json); } return new GameSettings(); // Return default settings if none are saved } #endregion }