using System.IO; using UnityEngine; using UnityEngine.UI; using System.Collections; public class GameManager : MonoBehaviour { public BeatmapManager beatmapManager; // 负责加载和管理谱面 public NoteSpawner noteSpawner; // 音符生成器 public AudioSource musicSource; // 音乐播放器 [Header("paths")] // 变量声明不再从静态变量中读取 public string JSONPath; public string audioPath; public string bgPicPath; // Optional: sprite renderer to show background image public SpriteRenderer backgroundRenderer; // NEW: UI Text to display banflag content from pressStart [Header("Debug / Test")] public Text banflagTextUI; private bool pauseSubscribed = false; private void SubscribeToPauseManager() { if (pauseSubscribed) return; // prefer the singleton, but try to find in scene if null var pm = PauseManager.Instance ?? FindObjectOfType(); if (pm != null) { pm.OnPauseStateChanged += HandlePauseStateChanged; pauseSubscribed = true; } } private void UnsubscribeFromPauseManager() { if (!pauseSubscribed) return; var pm = PauseManager.Instance ?? FindObjectOfType(); if (pm != null) { pm.OnPauseStateChanged -= HandlePauseStateChanged; } pauseSubscribed = false; } private void OnEnable() { SubscribeToPauseManager(); } private void OnDisable() { UnsubscribeFromPauseManager(); } private void HandlePauseStateChanged(bool isPaused) { if (musicSource != null) { if (isPaused) { musicSource.Pause(); } else { musicSource.UnPause(); } } } void Start() { Debug.Log("GameManager Start() 被调用"); // 检查关键组件是否为空 if (beatmapManager == null) Debug.LogError("beatmapManager 未赋值!"); if (noteSpawner == null) Debug.LogError("noteSpawner 未赋值!"); if (musicSource == null) Debug.LogError("musicSource 未赋值!"); // 如果 pressStart 已经读取了 banflag 内容,则把它显示在 UI(如果分配了) if (banflagTextUI != null && !string.IsNullOrEmpty(pressStart.banflagContent)) { banflagTextUI.text = pressStart.banflagContent; Debug.Log("Displayed banflag content from pressStart into banflagTextUI."); } // 在 test mode 下使用外部路径预加载资源并暂停系统,等待按空格继续 if (GameConfig.testMode) { // 延迟赋值:在 Start() 中获取静态路径,此时 pressStart.cs 已经运行并更新了它们 JSONPath = pressStart.testmode_beatmapJSON_path; audioPath = pressStart.testmode_audioFile_path; bgPicPath = pressStart.testmode_bgPicFile_path; Debug.Log("Test mode active: using external paths to preload assets"); // also update banflag UI if content exists if (banflagTextUI != null && !string.IsNullOrEmpty(pressStart.banflagContent)) { banflagTextUI.text = pressStart.banflagContent; } StartCoroutine(HandleTestModeStartup()); return; } else { StartCoroutine(HandleNormalModeStartup()); } } private IEnumerator HandleTestModeStartup() { // Preload audio from audioPath (absolute) if (!string.IsNullOrEmpty(audioPath)) { if (!File.Exists(audioPath)) { Debug.LogError($"TestMode audio file not found: {audioPath}"); } else { // 注意:这里仍然使用过时的 WWW,建议替换为 UnityWebRequest string url = "file://" + audioPath; using (var www = new WWW(url)) { yield return www; if (!string.IsNullOrEmpty(www.error)) { Debug.LogError($"加载测试模式音频失败: {www.error}"); } else { try { AudioClip clip = www.GetAudioClip(false, false); if (clip == null) { Debug.LogError("从文件获取 AudioClip 失败"); } else { musicSource.clip = clip; musicSource.loop = false; Debug.Log("TestMode audio loaded into AudioSource"); } } catch (System.Exception ex) { Debug.LogError($"将音频设置到 AudioSource 时出错: {ex}"); } } } } } else { Debug.LogWarning("TestMode audioPath 未配置。"); } // Preload background image into sprite renderer if (backgroundRenderer != null) { if (!string.IsNullOrEmpty(bgPicPath)) { if (!File.Exists(bgPicPath)) { Debug.LogError($"TestMode background image not found: {bgPicPath}"); } else { byte[] imgBytes = null; try { imgBytes = File.ReadAllBytes(bgPicPath); } catch (System.Exception ex) { Debug.LogError($"读取背景图片文件出错: {ex}"); } if (imgBytes != null) { Texture2D tex = new Texture2D(2, 2); if (tex.LoadImage(imgBytes)) { Sprite s = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f)); backgroundRenderer.sprite = s; // 【修改点:设置 SpriteRenderer 透明度为 255 (1.0f)】 Color color = backgroundRenderer.color; color.a = 1.0f; backgroundRenderer.color = color; // 保持比例不变的最大适应由场景布局决定,记录 assignment Debug.Log("Background sprite assigned (ensure your SpriteRenderer size fits scene)"); } else { Debug.LogError($"无法从字节创建 Texture2D: {bgPicPath}"); } } } } else { Debug.LogWarning("TestMode bgPicPath 未配置。"); } } else { Debug.LogWarning("backgroundRenderer 未配置,跳过背景加载。"); } // Read JSON from JSONPath and parse via BeatmapManager.ParseJsonOnly if (!string.IsNullOrEmpty(JSONPath)) { if (!File.Exists(JSONPath)) { Debug.LogError($"TestMode beatmap JSON not found: {JSONPath}"); yield break; // abort } string jsonContent = null; try { jsonContent = File.ReadAllText(JSONPath); } catch (System.Exception ex) { Debug.LogError($"读取 TestMode JSON 文件出错: {ex}"); yield break; } bool parsed = beatmapManager.ParseJsonOnly(jsonContent); if (!parsed) { Debug.LogError("ParseJsonOnly 失败,停止启动测试模式。"); yield break; } // Do not start spawning yet. We will start after unpausing. Debug.Log("Beatmap parsed (deferred start). Ready to unpause."); } else { Debug.LogError("TestMode JSONPath 未配置。"); yield break; } // Pause the system until Space pressed // Ensure we are subscribed before invoking pause so we track audio state SubscribeToPauseManager(); PauseManager.Instance?.Pause(true); UpdateStatusOnConsole("Paused: press Space to start playback"); // Wait for space key down (use unscaled input loop) while (!Input.GetKeyDown(KeyCode.Space)) { yield return null; } // Resume using PauseManager PauseManager.Instance?.Pause(false); // Start spawning using the parsed beatmap if (beatmapManager.beatmap != null) { beatmapManager.LoadBeatmap(beatmapManager.beatmap); } else { Debug.LogError("启动播放失败:beatmap 未解析或为空"); yield break; } // If audio clip was loaded into musicSource.clip, play now with delay from parsed globalDelaySeconds float delaySeconds = beatmapManager != null ? beatmapManager.globalDelaySeconds : 0f; if (musicSource.clip != null) { if (delaySeconds > 0f) { musicSource.PlayDelayed(delaySeconds); Debug.Log($"Scheduled test-mode music to play after {delaySeconds} seconds."); } else { musicSource.Play(); } } else { Debug.LogWarning("TestMode: no audio clip loaded into AudioSource; skipping play."); } UpdateStatusOnConsole("Playback started"); } private IEnumerator HandleNormalModeStartup() { // 加载谱面但不生成音符 string beatmapFilePath = Path.Combine(Application.streamingAssetsPath, "Emilia_demo.json"); if (!File.Exists(beatmapFilePath)) { Debug.LogError($"谱面文件不存在: {beatmapFilePath}"); yield break; } string json = File.ReadAllText(beatmapFilePath); bool parsed = beatmapManager.ParseJsonOnly(json); if (!parsed) { Debug.LogError("ParseJsonOnly 失败"); yield break; } // 暂停系统 SubscribeToPauseManager(); PauseManager.Instance?.Pause(true); UpdateStatusOnConsole("Paused: press Space to start playback"); // 等待空格 while (!Input.GetKeyDown(KeyCode.Space)) { yield return null; } // 恢复 PauseManager.Instance?.Pause(false); // 生成音符 if (beatmapManager.beatmap != null) { noteSpawner.LoadBeatmap(beatmapManager.beatmap); } else { Debug.LogError("beatmap 未解析"); yield break; } // 播放背景音乐(延迟播放由 beatmapManager.globalDelaySeconds 决定) if (!string.IsNullOrEmpty(beatmapManager.parsedMusicFile)) { AudioClip musicClip = Resources.Load(beatmapManager.parsedMusicFile); if (musicClip == null) { Debug.LogError($"音乐文件加载失败: {beatmapManager.parsedMusicFile}"); } else { musicSource.clip = musicClip; float delay = beatmapManager.globalDelaySeconds; if (delay > 0f) { musicSource.PlayDelayed(delay); Debug.Log($"Scheduled music to play after {delay} seconds."); } else { musicSource.Play(); } } } else { Debug.LogError("谱面中 musicFile 为空!"); } UpdateStatusOnConsole("Playback started"); } private void UpdateStatusOnConsole(string message) { Debug.Log(message); } }