Files
bansonic_beta_main/Assets/scripts/gamePlay_gameplay/BeatmapManager.cs
T

292 lines
10 KiB
C#

using System.IO;
using UnityEngine;
using UnityEngine.UI;
public class BeatmapManager : MonoBehaviour
{
public Beatmap beatmap; // 当前谱面数据
// 音符生成器引用
public NoteSpawner noteSpawner;
// Extra fields from beatmap JSON (stored temporarily)
[HideInInspector] public string parsedTitle;
[HideInInspector] public string parsedComposer;
[HideInInspector] public string parsedIllustrator;
[HideInInspector] public string parsedCharter;
[HideInInspector] public string parsedBeatmapId;
[HideInInspector] public string parsedDifficultyName;
[HideInInspector] public string parsedCreatedDate;
[HideInInspector] public string parsedLastSavedTime;
[HideInInspector] public string parsedMusicFile;
[HideInInspector] public string parsedBackgroundFile;
[HideInInspector] public int parsedDuration; // as int per request
[HideInInspector] public int parsedBpm; // as int per request
[HideInInspector] public int parsedDifficulty; // duplicate of beatmap.difficulty
[HideInInspector] public int parsedNoteAmount;
[HideInInspector] public float globalDelaySeconds = 0f;
// 从 JSON 文件加载谱面数据
public void LoadBeatmap(string fileName)
{
string path = Application.streamingAssetsPath + "/" + fileName;
if (File.Exists(path))
{
string json = File.ReadAllText(path);
Debug.Log("谱面 JSON 已读取: " + path);
ProcessJsonAndLoad(json);
}
else
{
Debug.LogError("文件不存在:" + path);
}
}
// 新增:从原始 JSON 字符串加载谱面(允许任意磁盘路径先读取后传入)
public void LoadBeatmapFromJsonString(string json)
{
if (string.IsNullOrEmpty(json))
{
Debug.LogError("LoadBeatmapFromJsonString: json is null or empty");
return;
}
ProcessJsonAndLoad(json);
}
// 新增:解析 JSON 但不启动 NoteSpawner(用于 test mode 的延迟开始)
public bool ParseJsonOnly(string json)
{
if (string.IsNullOrEmpty(json))
{
Debug.LogError("ParseJsonOnly: json is empty");
return false;
}
// Parse main beatmap
Beatmap parsed = null;
try
{
parsed = JsonUtility.FromJson<Beatmap>(json);
}
catch (System.Exception ex)
{
Debug.LogError($"ParseJsonOnly 解析 Beatmap 失败: {ex}");
return false;
}
if (parsed == null)
{
Debug.LogError("ParseJsonOnly: 解析 Beatmap 返回 null");
return false;
}
// Parse extras
BeatmapExtra extra = null;
try
{
extra = JsonUtility.FromJson<BeatmapExtra>(json);
}
catch { extra = null; }
if (extra != null)
{
parsedTitle = extra.title;
parsedComposer = extra.composer;
parsedIllustrator = extra.illustrator;
parsedCharter = extra.charter;
parsedBeatmapId = extra.beatmapId;
parsedDifficultyName = extra.difficultyName;
parsedCreatedDate = extra.createdDate;
parsedLastSavedTime = extra.lastSavedTime;
parsedMusicFile = extra.musicFile;
parsedBackgroundFile = extra.backgroundFile;
parsedDuration = extra.duration;
parsedBpm = extra.bpm;
parsedDifficulty = extra.difficulty;
parsedNoteAmount = extra.noteAmount;
globalDelaySeconds = extra.globalDelaySeconds;
if (!string.IsNullOrEmpty(extra.musicFile)) parsed.musicFile = extra.musicFile;
if (!string.IsNullOrEmpty(extra.backgroundFile)) parsed.backgroundFile = extra.backgroundFile;
}
else
{
parsedTitle = parsed.title;
parsedComposer = parsed.composer;
parsedIllustrator = parsed.illustrator;
parsedCharter = parsed.charter;
parsedBeatmapId = parsed.beatmapId;
parsedDifficultyName = parsed.difficultyName;
parsedCreatedDate = parsed.createdDate;
parsedMusicFile = parsed.musicFile;
parsedBackgroundFile = parsed.backgroundFile;
parsedDuration = Mathf.RoundToInt(parsed.duration);
parsedBpm = Mathf.RoundToInt(parsed.bpm);
parsedDifficulty = parsed.difficulty;
}
// NOTE: Do NOT modify parsed.notes here. globalDelaySeconds will be applied to audio playback instead.
beatmap = parsed;
Debug.Log("ParseJsonOnly: parsed beatmap " + beatmap.title);
return true;
}
// 直接传入已经解析的 Beatmap(兼容旧调用)
public void LoadBeatmap(Beatmap loadedBeatmap)
{
beatmap = loadedBeatmap;
Debug.Log("谱面已加载(来自 Beatmap 对象):" + (beatmap != null ? beatmap.title : "null"));
// No globalDelaySeconds available in this path. Call NoteSpawner directly.
noteSpawner.LoadBeatmap(beatmap);
}
// 读取并加载当前谱面到音符生成器(备用)
public void LoadBeatmapFromFile()
{
string path = Application.streamingAssetsPath + "/Emilia_demo.json";
if (File.Exists(path))
{
string json = File.ReadAllText(path);
ProcessJsonAndLoad(json);
}
else
{
Debug.LogError("谱面文件未找到!");
}
}
// 在 Start() 方法中初始化
void Start()
{
// 如果处于测试模式,则跳过自动加载谱面
if (GameConfig.testMode)
{
Debug.Log("Test mode active: skipping automatic beatmap load in BeatmapManager.Start");
}
else
{
// 加载默认谱面
LoadBeatmap("Emilia_demo.json"); // 加载并实例化音符
}
}
// Helper class used to parse extra fields from JSON that Beatmap doesn't define
[System.Serializable]
private class BeatmapExtra
{
public string title;
public string composer;
public string illustrator;
public string charter;
public string beatmapId;
public int duration; // as int per request
public int bpm; // as int per request
public int difficulty;
public string difficultyName;
public string createdDate;
public string lastSavedTime;
public string musicFile;
public string backgroundFile;
public int noteAmount;
public float globalDelaySeconds;
}
// Parse JSON string to Beatmap and extras, then pass to NoteSpawner
private void ProcessJsonAndLoad(string json)
{
if (string.IsNullOrEmpty(json))
{
Debug.LogError("ProcessJsonAndLoad: json is empty");
return;
}
// Parse main beatmap
Beatmap parsed = null;
try
{
parsed = JsonUtility.FromJson<Beatmap>(json);
}
catch (System.Exception ex)
{
Debug.LogError($"解析 Beatmap 失败: {ex}");
return;
}
if (parsed == null)
{
Debug.LogError("解析 Beatmap 返回 null");
return;
}
// Parse extras using BeatmapExtra which contains the requested fields and types
BeatmapExtra extra = null;
try
{
extra = JsonUtility.FromJson<BeatmapExtra>(json);
}
catch { extra = null; }
if (extra != null)
{
// store into manager fields
parsedTitle = extra.title;
parsedComposer = extra.composer;
parsedIllustrator = extra.illustrator;
parsedCharter = extra.charter;
parsedBeatmapId = extra.beatmapId;
parsedDifficultyName = extra.difficultyName;
parsedCreatedDate = extra.createdDate;
parsedLastSavedTime = extra.lastSavedTime;
parsedMusicFile = extra.musicFile;
parsedBackgroundFile = extra.backgroundFile;
parsedDuration = extra.duration;
parsedBpm = extra.bpm;
parsedDifficulty = extra.difficulty;
parsedNoteAmount = extra.noteAmount;
globalDelaySeconds = extra.globalDelaySeconds;
// If JSON contains absolute paths for music/background, copy into parsed object for later use
if (!string.IsNullOrEmpty(extra.musicFile)) parsed.musicFile = extra.musicFile;
if (!string.IsNullOrEmpty(extra.backgroundFile)) parsed.backgroundFile = extra.backgroundFile;
Debug.Log($"Beatmap extras parsed: title={parsedTitle}, composer={parsedComposer}, duration={parsedDuration}, bpm={parsedBpm}, difficulty={parsedDifficulty}, noteAmount={parsedNoteAmount}, globalDelaySeconds={globalDelaySeconds}");
}
else
{
// Fallback to populate from parsed Beatmap where possible
parsedTitle = parsed.title;
parsedComposer = parsed.composer;
parsedIllustrator = parsed.illustrator;
parsedCharter = parsed.charter;
parsedBeatmapId = parsed.beatmapId;
parsedDifficultyName = parsed.difficultyName;
parsedCreatedDate = parsed.createdDate;
parsedMusicFile = parsed.musicFile;
parsedBackgroundFile = parsed.backgroundFile;
// convert types
parsedDuration = Mathf.RoundToInt(parsed.duration);
parsedBpm = Mathf.RoundToInt(parsed.bpm);
parsedDifficulty = parsed.difficulty;
Debug.LogWarning("BeatmapExtra not found in JSON; populated limited fields from Beatmap.");
}
// NOTE: Do NOT modify parsed.notes here. globalDelaySeconds will be applied to audio playback instead.
// assign and hand off to spawner
beatmap = parsed;
Debug.Log("谱面已加载:" + beatmap.title);
noteSpawner.LoadBeatmap(beatmap);
}
}