技能主要更新,修复卡顿并加入动画,以及各种其他更新。
This commit is contained in:
@@ -77,7 +77,15 @@ public class SongButton : MonoBehaviour
|
||||
{
|
||||
Debug.Log("SetButtonData called, songID: " + songID);
|
||||
|
||||
var sd = SongDataLibrary.Instance != null ? SongDataLibrary.Instance.GetSongDataByID(songID) : null;
|
||||
SongData sd = null;
|
||||
if (SongDataLibrary.Instance != null)
|
||||
{
|
||||
sd = SongDataLibrary.Instance.GetSongDataByID(songID);
|
||||
}
|
||||
if (sd == null)
|
||||
{
|
||||
sd = thisSong_so as SongData;
|
||||
}
|
||||
if (sd != null)
|
||||
{
|
||||
if (songNameText != null) songNameText.text = sd.songName;
|
||||
@@ -206,9 +214,25 @@ public class SongButton : MonoBehaviour
|
||||
public void OnSongButtonClick()
|
||||
{
|
||||
Debug.Log("Song button clicked, song_songSerialID: " + song_songSerialID);
|
||||
SongData selectedSong = SongDataLibrary.Instance.GetSongDataByID(song_songSerialID);
|
||||
SongData selectedSong = null;
|
||||
if (SongDataLibrary.Instance != null)
|
||||
{
|
||||
selectedSong = SongDataLibrary.Instance.GetSongDataByID(song_songSerialID);
|
||||
}
|
||||
if (selectedSong == null)
|
||||
{
|
||||
selectedSong = thisSong_so as SongData;
|
||||
}
|
||||
if (selectedSong != null)
|
||||
{
|
||||
int bestTotal = 0;
|
||||
int bestDiff = -1;
|
||||
string bestDiffName = "";
|
||||
selectedSong.GetAbsoluteHighestScore(out bestTotal, out bestDiff, out bestDiffName);
|
||||
if (bestDiff >= 0)
|
||||
{
|
||||
selectedSong.thisLevel_selectedDifficultyID = bestDiff;
|
||||
}
|
||||
if (currentSelected != null && currentSelected != this)
|
||||
{
|
||||
currentSelected.FadeOutSelectedBorder();
|
||||
@@ -217,7 +241,7 @@ public class SongButton : MonoBehaviour
|
||||
FadeInSelectedBorder();
|
||||
|
||||
SongDataHolder.SelectedSongData = selectedSong;
|
||||
var selectedInfo = FindObjectOfType<selected_songInfo>();
|
||||
var selectedInfo = Object.FindAnyObjectByType<selected_songInfo>();
|
||||
if (selectedInfo != null)
|
||||
{
|
||||
selectedInfo.UpdateSelectedSongDisplay();
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using TMPro;
|
||||
using UnityEngine.SceneManagement;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using DG.Tweening;
|
||||
|
||||
public class SongSelectUI : MonoBehaviour
|
||||
{
|
||||
@@ -13,12 +14,31 @@ public class SongSelectUI : MonoBehaviour
|
||||
|
||||
[SerializeField] Button button_Main;
|
||||
[SerializeField] string ui_Main_Scene_Name = "UI_UI";
|
||||
[Header("Enter Animation")]
|
||||
[SerializeField] bool play_Enter_Anim = true;
|
||||
[SerializeField] float enter_Anim_Delay = 0.05f;
|
||||
[Header("Async Build")]
|
||||
[SerializeField] bool useAsyncBuild = true;
|
||||
[SerializeField] int buildBatch = 8;
|
||||
[Header("Switch Animations")]
|
||||
[SerializeField] bool play_Switch_Anim = true;
|
||||
[SerializeField] RectTransform list_Anim_Root;
|
||||
[SerializeField] float list_FadeOut_Time = 0.12f;
|
||||
[SerializeField] float list_FadeIn_Time = 0.18f;
|
||||
[SerializeField] float list_Move_Offset = 24f;
|
||||
[SerializeField] Ease list_Move_Ease = Ease.OutCubic;
|
||||
[SerializeField] bool list_Use_Unscaled = true;
|
||||
|
||||
// Current DLC key used for per-DLC saved song selection
|
||||
public static string CurrentDlcKey = "dlc_default_0";
|
||||
|
||||
// Track pending restore to avoid multiple overlapping restores
|
||||
private Coroutine restoreCoroutine;
|
||||
private Coroutine buildCoroutine;
|
||||
private Coroutine switchCoroutine;
|
||||
private CanvasGroup listCanvasGroup;
|
||||
private Vector2 listBasePos;
|
||||
private bool listBaseCached;
|
||||
|
||||
void Start()
|
||||
{
|
||||
@@ -29,36 +49,201 @@ public class SongSelectUI : MonoBehaviour
|
||||
}
|
||||
|
||||
button_Main.onClick.AddListener(
|
||||
() => SceneManager.LoadScene(ui_Main_Scene_NAME(), LoadSceneMode.Single));
|
||||
() => StartCoroutine(LoadSceneAsync(ui_Main_Scene_NAME())));
|
||||
// Do not populate the song list at start. DLC buttons will request songs when clicked.
|
||||
|
||||
if (play_Enter_Anim)
|
||||
{
|
||||
UI_SelectSong_EnterAnim anim = GetComponent<UI_SelectSong_EnterAnim>();
|
||||
if (anim == null)
|
||||
{
|
||||
anim = gameObject.AddComponent<UI_SelectSong_EnterAnim>();
|
||||
}
|
||||
anim.SetDelay(enter_Anim_Delay);
|
||||
anim.Play();
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator LoadSceneAsync(string sceneName)
|
||||
{
|
||||
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Single);
|
||||
while (!asyncLoad.isDone)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
// 显示所有歌曲 (kept for manual use)
|
||||
public void DisplaySongs()
|
||||
{
|
||||
ClearSongList();
|
||||
|
||||
foreach (SongData song in songList.songs)
|
||||
{
|
||||
InstantiateSongButton(song);
|
||||
}
|
||||
|
||||
if (restoreCoroutine != null) StopCoroutine(restoreCoroutine);
|
||||
restoreCoroutine = StartCoroutine(RestoreSelectedSongNextFrame());
|
||||
DisplaySongsFromList(songList != null ? songList.songs : null);
|
||||
}
|
||||
|
||||
// Instantiate from a provided list (used by dlcButton to show DLC songs)
|
||||
public void DisplaySongsFromList(List<SongData> list)
|
||||
{
|
||||
ClearSongList();
|
||||
if (buildCoroutine != null)
|
||||
{
|
||||
StopCoroutine(buildCoroutine);
|
||||
}
|
||||
if (switchCoroutine != null)
|
||||
{
|
||||
StopCoroutine(switchCoroutine);
|
||||
switchCoroutine = null;
|
||||
}
|
||||
if (play_Switch_Anim)
|
||||
{
|
||||
switchCoroutine = StartCoroutine(SwitchSongsRoutine(list));
|
||||
}
|
||||
else
|
||||
{
|
||||
buildCoroutine = StartCoroutine(BuildSongsAsync(list));
|
||||
}
|
||||
}
|
||||
|
||||
if (list == null) return;
|
||||
private IEnumerator SwitchSongsRoutine(List<SongData> list)
|
||||
{
|
||||
yield return PlayListSwitchOut();
|
||||
yield return BuildSongsAsync(list);
|
||||
yield return PlayListSwitchIn();
|
||||
switchCoroutine = null;
|
||||
}
|
||||
|
||||
private IEnumerator BuildSongsAsync(List<SongData> list)
|
||||
{
|
||||
ClearSongList();
|
||||
if (list == null)
|
||||
{
|
||||
buildCoroutine = null;
|
||||
yield break;
|
||||
}
|
||||
|
||||
// allow UI to render a frame before heavy instantiation
|
||||
yield return null;
|
||||
|
||||
int count = 0;
|
||||
foreach (var song in list)
|
||||
{
|
||||
InstantiateSongButton(song);
|
||||
count++;
|
||||
if (useAsyncBuild && buildBatch > 0 && (count % buildBatch) == 0)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
// After populating, attempt to restore per-DLC selected song (next frame to avoid stale objects)
|
||||
if (restoreCoroutine != null) StopCoroutine(restoreCoroutine);
|
||||
restoreCoroutine = StartCoroutine(RestoreSelectedSongNextFrame());
|
||||
buildCoroutine = null;
|
||||
}
|
||||
|
||||
private RectTransform GetListAnimRoot()
|
||||
{
|
||||
if (list_Anim_Root != null)
|
||||
{
|
||||
return list_Anim_Root;
|
||||
}
|
||||
return contentPanel as RectTransform;
|
||||
}
|
||||
|
||||
private CanvasGroup EnsureListCanvasGroup(RectTransform root)
|
||||
{
|
||||
if (root == null) return null;
|
||||
if (listCanvasGroup == null || listCanvasGroup.gameObject != root.gameObject)
|
||||
{
|
||||
listCanvasGroup = root.GetComponent<CanvasGroup>();
|
||||
if (listCanvasGroup == null)
|
||||
{
|
||||
listCanvasGroup = root.gameObject.AddComponent<CanvasGroup>();
|
||||
}
|
||||
}
|
||||
return listCanvasGroup;
|
||||
}
|
||||
|
||||
private void CacheListBase(RectTransform root)
|
||||
{
|
||||
if (root == null) return;
|
||||
if (!listBaseCached)
|
||||
{
|
||||
listBasePos = root.anchoredPosition;
|
||||
listBaseCached = true;
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator PlayListSwitchOut()
|
||||
{
|
||||
if (!play_Switch_Anim)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
RectTransform root = GetListAnimRoot();
|
||||
if (root == null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
CacheListBase(root);
|
||||
CanvasGroup cg = EnsureListCanvasGroup(root);
|
||||
if (cg == null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
root.DOKill();
|
||||
cg.DOKill();
|
||||
float moveOffset = list_Move_Offset;
|
||||
if (root.GetComponent<LayoutGroup>() != null)
|
||||
{
|
||||
moveOffset = 0f;
|
||||
}
|
||||
Sequence seq = DOTween.Sequence().SetUpdate(list_Use_Unscaled);
|
||||
seq.Join(cg.DOFade(0f, list_FadeOut_Time));
|
||||
if (Mathf.Abs(moveOffset) > 0.01f)
|
||||
{
|
||||
seq.Join(root.DOAnchorPos(listBasePos + new Vector2(-moveOffset, 0f), list_FadeOut_Time).SetEase(list_Move_Ease));
|
||||
}
|
||||
yield return seq.WaitForCompletion();
|
||||
}
|
||||
|
||||
private IEnumerator PlayListSwitchIn()
|
||||
{
|
||||
if (!play_Switch_Anim)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
RectTransform root = GetListAnimRoot();
|
||||
if (root == null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
CacheListBase(root);
|
||||
CanvasGroup cg = EnsureListCanvasGroup(root);
|
||||
if (cg == null)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
root.DOKill();
|
||||
cg.DOKill();
|
||||
float moveOffset = list_Move_Offset;
|
||||
if (root.GetComponent<LayoutGroup>() != null)
|
||||
{
|
||||
moveOffset = 0f;
|
||||
}
|
||||
if (Mathf.Abs(moveOffset) > 0.01f)
|
||||
{
|
||||
root.anchoredPosition = listBasePos + new Vector2(moveOffset, 0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
root.anchoredPosition = listBasePos;
|
||||
}
|
||||
cg.alpha = 0f;
|
||||
Sequence seq = DOTween.Sequence().SetUpdate(list_Use_Unscaled);
|
||||
seq.Join(cg.DOFade(1f, list_FadeIn_Time));
|
||||
if (Mathf.Abs(moveOffset) > 0.01f)
|
||||
{
|
||||
seq.Join(root.DOAnchorPos(listBasePos, list_FadeIn_Time).SetEase(list_Move_Ease));
|
||||
}
|
||||
yield return seq.WaitForCompletion();
|
||||
}
|
||||
|
||||
private IEnumerator RestoreSelectedSongNextFrame()
|
||||
@@ -135,10 +320,25 @@ public class SongSelectUI : MonoBehaviour
|
||||
GameObject songButtonObj = Instantiate(songButtonPrefab, contentPanel);
|
||||
songButtonObj.transform.SetParent(contentPanel, false);
|
||||
|
||||
SongData sd = song;
|
||||
if (SongDataLibrary.Instance != null && SongDataLibrary.Instance.IsLoaded)
|
||||
{
|
||||
sd = SongDataLibrary.Instance.GetSongDataByID(song.songID) ?? song;
|
||||
}
|
||||
int bestTotal = sd != null ? sd.personalRecord : song.personalRecord;
|
||||
int bestDiff = -1;
|
||||
string bestDiffName = "";
|
||||
if (sd != null)
|
||||
{
|
||||
sd.GetAbsoluteHighestScore(out bestTotal, out bestDiff, out bestDiffName);
|
||||
}
|
||||
|
||||
SongButton songButton = songButtonObj.GetComponent<SongButton>();
|
||||
if (songButton != null)
|
||||
{
|
||||
songButton.SetButtonData(song.songName, song.personalRecord, song.difficultyID, song.illustration, song.songID);
|
||||
songButton.thisSong_so = sd != null ? sd : song;
|
||||
int diffForDisplay = bestDiff >= 0 ? bestDiff : song.difficultyID;
|
||||
songButton.SetButtonData(song.songName, bestTotal, diffForDisplay, song.illustration, song.songID);
|
||||
}
|
||||
|
||||
Image songImage = songButtonObj.GetComponentInChildren<Image>();
|
||||
@@ -153,8 +353,15 @@ public class SongSelectUI : MonoBehaviour
|
||||
if (texts.Length >= 4)
|
||||
{
|
||||
texts[0].text = song.songName;
|
||||
texts[1].text = "Record : " + song.personalRecord;
|
||||
texts[3].text = "" + song.difficultyID;
|
||||
texts[1].text = "Record : " + bestTotal;
|
||||
if (bestTotal <= 0)
|
||||
{
|
||||
texts[3].text = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
texts[3].text = string.IsNullOrEmpty(bestDiffName) ? bestDiff.ToString() : bestDiffName;
|
||||
}
|
||||
texts[2].text = "SongID : " + song.songID.ToString();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,22 +1,34 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
|
||||
public class SongDataLibrary : MonoBehaviour
|
||||
{
|
||||
public static SongDataLibrary Instance;
|
||||
private Dictionary<int, SongData> songDataDictionary = new Dictionary<int, SongData>();
|
||||
|
||||
// 指定存放在 "song_songIndex" 目录下的各个子文件夹名称
|
||||
// 例如:如果你有 Assets/Resources/song_songIndex/FolderA 和 FolderB,则在 Inspector 中填写 { "FolderA", "FolderB" }
|
||||
// ָ������� "song_songIndex" Ŀ¼�µĸ������ļ�������
|
||||
// ���磺������� Assets/Resources/song_songIndex/FolderA �� FolderB������ Inspector ����д { "FolderA", "FolderB" }
|
||||
public string[] subfolderNames;
|
||||
|
||||
[Header("Song List")]
|
||||
[SerializeField] SongList songList;
|
||||
[SerializeField] bool useSongListIfAvailable = true;
|
||||
|
||||
[Header("Async Load Settings")]
|
||||
[SerializeField] int yieldEvery = 16;
|
||||
[SerializeField] bool logLoadProgress = false;
|
||||
|
||||
public bool IsLoaded { get; private set; }
|
||||
public bool IsLoading { get; private set; }
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (Instance == null)
|
||||
{
|
||||
Instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
LoadSongData();
|
||||
StartCoroutine(LoadSongDataCoroutine());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -24,49 +36,141 @@ public class SongDataLibrary : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadSongData()
|
||||
private IEnumerator LoadSongDataCoroutine()
|
||||
{
|
||||
// 先加载直接放在 "song_songIndex" 目录下的 SongData
|
||||
SongData[] assets = Resources.LoadAll<SongData>("song_songIndex");
|
||||
foreach (SongData data in assets)
|
||||
if (IsLoading || IsLoaded)
|
||||
{
|
||||
if (!songDataDictionary.ContainsKey(data.songID))
|
||||
yield break;
|
||||
}
|
||||
|
||||
IsLoading = true;
|
||||
songDataDictionary.Clear();
|
||||
|
||||
// Allow one frame to render before heavy load begins
|
||||
yield return null;
|
||||
|
||||
// prefer SongList if available to avoid heavy Resources.LoadAll
|
||||
if (useSongListIfAvailable)
|
||||
{
|
||||
if (songList == null)
|
||||
{
|
||||
songDataDictionary.Add(data.songID, data);
|
||||
Debug.Log("加载到 SongData, songID: " + data.songID + ", 名称: " + data.songName);
|
||||
SongSelectUI ui = Object.FindAnyObjectByType<SongSelectUI>();
|
||||
if (ui != null)
|
||||
{
|
||||
songList = ui.songList;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (songList != null && songList.songs != null && songList.songs.Count > 0)
|
||||
{
|
||||
Debug.LogWarning("重复的 songID: " + data.songID);
|
||||
yield return LoadFromList(songList.songs, "songList");
|
||||
IsLoaded = true;
|
||||
IsLoading = false;
|
||||
yield break;
|
||||
}
|
||||
}
|
||||
|
||||
// 再遍历每个子文件夹,加载其中的 SongData
|
||||
foreach (string subfolder in subfolderNames)
|
||||
yield return LoadFromPath("song_songIndex", "root");
|
||||
|
||||
if (subfolderNames != null)
|
||||
{
|
||||
SongData[] subAssets = Resources.LoadAll<SongData>("song_songIndex/" + subfolder);
|
||||
foreach (SongData data in subAssets)
|
||||
for (int i = 0; i < subfolderNames.Length; i++)
|
||||
{
|
||||
if (!songDataDictionary.ContainsKey(data.songID))
|
||||
string subfolder = subfolderNames[i];
|
||||
if (string.IsNullOrEmpty(subfolder))
|
||||
{
|
||||
songDataDictionary.Add(data.songID, data);
|
||||
Debug.Log("从 " + subfolder + " 加载到 SongData, songID: " + data.songID + ", 名称: " + data.songName);
|
||||
continue;
|
||||
}
|
||||
else
|
||||
yield return LoadFromPath("song_songIndex/" + subfolder, subfolder);
|
||||
// yield a frame between folders to reduce hitch
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
IsLoaded = true;
|
||||
IsLoading = false;
|
||||
}
|
||||
|
||||
private IEnumerator LoadFromPath(string path, string label)
|
||||
{
|
||||
SongData[] assets = Resources.LoadAll<SongData>(path);
|
||||
if (assets == null || assets.Length == 0)
|
||||
{
|
||||
if (logLoadProgress)
|
||||
{
|
||||
Debug.Log("SongDataLibrary: no assets found at '" + path + "'");
|
||||
}
|
||||
yield break;
|
||||
}
|
||||
|
||||
int yielded = 0;
|
||||
foreach (SongData data in assets)
|
||||
{
|
||||
if (data == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!songDataDictionary.ContainsKey(data.songID))
|
||||
{
|
||||
songDataDictionary.Add(data.songID, data);
|
||||
if (logLoadProgress)
|
||||
{
|
||||
Debug.LogWarning("重复的 songID: " + data.songID);
|
||||
Debug.Log("Loaded SongData [" + label + "] songID: " + data.songID + ", name: " + data.songName);
|
||||
}
|
||||
}
|
||||
else if (logLoadProgress)
|
||||
{
|
||||
Debug.LogWarning("Duplicate songID: " + data.songID);
|
||||
}
|
||||
|
||||
yielded++;
|
||||
if (yieldEvery > 0 && (yielded % yieldEvery) == 0)
|
||||
{
|
||||
// yield to spread work across frames
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SongData GetSongDataByID(int songID)
|
||||
|
||||
private IEnumerator LoadFromList(List<SongData> list, string label)
|
||||
{
|
||||
if (list == null || list.Count == 0)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
int yielded = 0;
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
SongData data = list[i];
|
||||
if (data == null) continue;
|
||||
if (!songDataDictionary.ContainsKey(data.songID))
|
||||
{
|
||||
songDataDictionary.Add(data.songID, data);
|
||||
if (logLoadProgress)
|
||||
{
|
||||
Debug.Log("Loaded SongData [" + label + "] songID: " + data.songID + ", name: " + data.songName);
|
||||
}
|
||||
}
|
||||
else if (logLoadProgress)
|
||||
{
|
||||
Debug.LogWarning("Duplicate songID: " + data.songID);
|
||||
}
|
||||
|
||||
yielded++;
|
||||
if (yieldEvery > 0 && (yielded % yieldEvery) == 0)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
public SongData GetSongDataByID(int songID)
|
||||
{
|
||||
if (songDataDictionary.ContainsKey(songID))
|
||||
{
|
||||
return songDataDictionary[songID];
|
||||
}
|
||||
Debug.LogError("未找到 songID: " + songID);
|
||||
Debug.LogError("δ�ҵ� songID: " + songID);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,56 +3,67 @@ using UnityEngine;
|
||||
|
||||
public class SongDataManager : MonoBehaviour
|
||||
{
|
||||
// 保存 JSON 文件的目录路径
|
||||
// ���� JSON �ļ���Ŀ¼·��
|
||||
private string jsonDirectory;
|
||||
|
||||
[Header("Settings")]
|
||||
public bool autoSaveOnStart = false; // 默认关闭,仅在需要同步数据时手动开启
|
||||
|
||||
void Start()
|
||||
{
|
||||
// 获取持久化数据路径,并在其下创建 "SongDataJson" 文件夹
|
||||
// 获取持久化存储路径,并在该目录下创建 "SongDataJson" 文件夹
|
||||
jsonDirectory = Path.Combine(Application.persistentDataPath, "SongDataJson");
|
||||
|
||||
// 如果目录不存在,则创建目录
|
||||
// 如果目录不存在,则创建目录
|
||||
if (!Directory.Exists(jsonDirectory))
|
||||
{
|
||||
Directory.CreateDirectory(jsonDirectory);
|
||||
Debug.Log("创建 JSON 存储目录: " + jsonDirectory);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("JSON 存储目录已存在: " + jsonDirectory);
|
||||
Debug.Log("创建 JSON 存储目录: " + jsonDirectory);
|
||||
}
|
||||
|
||||
// 调用方法,将所有 SongData 资源转换为 JSON 并保存
|
||||
SaveAllSongDataToJson();
|
||||
// 只有开启了 autoSaveOnStart 且在编辑器模式下才自动执行
|
||||
if (autoSaveOnStart)
|
||||
{
|
||||
StartCoroutine(SaveAllSongDataToJsonRoutine());
|
||||
}
|
||||
}
|
||||
|
||||
void SaveAllSongDataToJson()
|
||||
public void TriggerSaveAllSongs()
|
||||
{
|
||||
// 从 Resources 文件夹下的 "SongData" 子目录加载所有 SongData 资源
|
||||
StartCoroutine(SaveAllSongDataToJsonRoutine());
|
||||
}
|
||||
|
||||
System.Collections.IEnumerator SaveAllSongDataToJsonRoutine()
|
||||
{
|
||||
// 从 Resources 文件夹下的 "song_songIndex" 子目录加载所有 SongData 资源
|
||||
SongData[] allSongData = Resources.LoadAll<SongData>("song_songIndex");
|
||||
|
||||
|
||||
// 如果没有加载到任何 SongData,输出警告信息
|
||||
if (allSongData.Length == 0)
|
||||
{
|
||||
Debug.LogWarning("未在 Resources/SongData 中找到任何 SongData 资源!");
|
||||
Debug.LogWarning("未在 Resources/song_songIndex 找到任何 SongData 资源。");
|
||||
yield break;
|
||||
}
|
||||
|
||||
// 遍历每个 SongData 资源
|
||||
foreach (SongData song in allSongData)
|
||||
Debug.Log($"开始异步保存 {allSongData.Length} 个歌曲数据...");
|
||||
|
||||
// 遍历每个 SongData 资源
|
||||
for (int i = 0; i < allSongData.Length; i++)
|
||||
{
|
||||
// 使用 SongDataSerializable 将 SongData 转换为可序列化对象
|
||||
SongData song = allSongData[i];
|
||||
// 使用 SongDataSerializable 将 SongData 转换为可序列化对象
|
||||
SongDataSerializable jsonData = new SongDataSerializable(song);
|
||||
// 将对象转换为 JSON 格式字符串,true 表示格式化输出(便于阅读)
|
||||
string json = JsonUtility.ToJson(jsonData, true);
|
||||
|
||||
// 构造 JSON 文件的完整路径,文件名使用 songID 命名,例如 "123.json"
|
||||
string filePath = Path.Combine(jsonDirectory, song.songID + ".json");
|
||||
|
||||
// 将 JSON 内容写入文件
|
||||
File.WriteAllText(filePath, json);
|
||||
// 输出调试信息,显示已保存的 JSON 文件路径
|
||||
Debug.Log("已保存 JSON 文件: " + filePath);
|
||||
|
||||
// 每处理 5 个文件等待一帧,防止主线程卡死
|
||||
if (i % 5 == 0)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log("所有 JSON 文件保存完毕。");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,41 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
|
||||
public class dlcButton : MonoBehaviour
|
||||
{
|
||||
[Header("基本套件")]
|
||||
[Header("������")]
|
||||
public Image dlc_profileImgae;
|
||||
public Text dlcName;
|
||||
public Text dlcID;
|
||||
public Text dlcProducer;
|
||||
public Text dlcPubliushDate;
|
||||
public Image dlc_nowSelectedImageBoarder;
|
||||
[Header("介绍")]
|
||||
[Header("����")]
|
||||
public Text dlcDescription;
|
||||
|
||||
[Header("DLC SO (可在 Inspector 指定)")]
|
||||
[Header("DLC SO (���� Inspector ָ��)")]
|
||||
public dlcData dlcDataSO;
|
||||
|
||||
[Header("DLC 内容 (运行时会由脚本填充)")]
|
||||
[Header("DLC ���� (����ʱ���ɽű����)")]
|
||||
public List<SongData> dlcContent = new List<SongData>();
|
||||
|
||||
[Header("搜索路径 (编辑器/运行时)")]
|
||||
[Header("����·�� (�༭��/����ʱ)")]
|
||||
public string editorSearchFolder = "Assets/Resources/dlc_dlcIndex";
|
||||
public string runtimeResourcesFolder = "Resources/dlc_dlcIndex";
|
||||
|
||||
private Button _btn;
|
||||
public bool Resolved { get; private set; }
|
||||
|
||||
// Shared cache to avoid repeated Resources.LoadAll scans
|
||||
private static Dictionary<int, dlcData> cachedById = new Dictionary<int, dlcData>();
|
||||
private static List<dlcData> cachedAll = new List<dlcData>();
|
||||
private static bool cacheBuilt = false;
|
||||
private static bool cacheBuilding = false;
|
||||
private static string cachedFolder = string.Empty;
|
||||
|
||||
|
||||
// Selection management (shared across all dlcButton instances)
|
||||
private static List<dlcButton> allButtons = new List<dlcButton>();
|
||||
@@ -206,7 +216,7 @@ public class dlcButton : MonoBehaviour
|
||||
// mark selection first
|
||||
Select();
|
||||
|
||||
var s = GameObject.FindObjectOfType<SongSelectUI>();
|
||||
var s = Object.FindAnyObjectByType<SongSelectUI>();
|
||||
if (s != null)
|
||||
{
|
||||
s.DisplaySongsFromList(dlcContent);
|
||||
@@ -388,41 +398,164 @@ public class dlcButton : MonoBehaviour
|
||||
// Resolve dlcData after all buttons have been instantiated
|
||||
public void ResolveDlcData()
|
||||
{
|
||||
if (Resolved)
|
||||
{
|
||||
return;
|
||||
}
|
||||
StartCoroutine(ResolveDlcDataAsync());
|
||||
}
|
||||
|
||||
public IEnumerator ResolveDlcDataAsync()
|
||||
{
|
||||
if (Resolved)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
|
||||
Debug.Log($"dlcButton.ResolveDlcData called on '{gameObject.name}'");
|
||||
|
||||
if (dlcDataSO != null)
|
||||
{
|
||||
Debug.Log($"dlcButton: dlcDataSO already assigned on '{gameObject.name}' -> {dlcDataSO.name}");
|
||||
ApplyDlcData(dlcDataSO);
|
||||
return;
|
||||
Resolved = true;
|
||||
yield break;
|
||||
}
|
||||
|
||||
int id = 0;
|
||||
int id;
|
||||
if (!TryGetResolveId(out id))
|
||||
{
|
||||
Debug.LogWarning($"dlcButton.ResolveDlcData: no dlcID text and no name to parse for '{gameObject.name}'");
|
||||
Resolved = true;
|
||||
yield break;
|
||||
}
|
||||
|
||||
yield return BuildCacheIfNeeded(runtimeResourcesFolder);
|
||||
|
||||
if (TryResolveFromCache(id))
|
||||
{
|
||||
Resolved = true;
|
||||
yield break;
|
||||
}
|
||||
|
||||
LoadContentBySongIdPrefix(id);
|
||||
Resolved = true;
|
||||
}
|
||||
|
||||
private bool TryGetResolveId(out int id)
|
||||
{
|
||||
id = 0;
|
||||
if (dlcID != null && int.TryParse(dlcID.text, out id))
|
||||
{
|
||||
Debug.Log($"dlcButton: Resolving by dlcID text {id} for '{gameObject.name}'");
|
||||
LoadDlcDataById(id);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
string goName = gameObject.name;
|
||||
if (!string.IsNullOrEmpty(goName))
|
||||
{
|
||||
var parts = goName.Split('_');
|
||||
int parsed = 0;
|
||||
if (parts.Length > 0 && int.TryParse(parts[0], out parsed))
|
||||
if (parts.Length > 0 && int.TryParse(parts[0], out id))
|
||||
{
|
||||
Debug.Log($"dlcButton: Resolving by GameObject name prefix {parsed} for '{gameObject.name}'");
|
||||
LoadDlcDataById(parsed);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"dlcButton.ResolveDlcData: could not parse id from GameObject name '{goName}'");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryResolveFromCache(int id)
|
||||
{
|
||||
if (!cacheBuilt)
|
||||
{
|
||||
Debug.LogWarning($"dlcButton.ResolveDlcData: no dlcID text and no name to parse for '{gameObject.name}'");
|
||||
return false;
|
||||
}
|
||||
|
||||
dlcData so;
|
||||
if (cachedById.TryGetValue(id, out so) && so != null)
|
||||
{
|
||||
dlcDataSO = so;
|
||||
ApplyDlcData(so);
|
||||
return true;
|
||||
}
|
||||
|
||||
string prefix = id.ToString();
|
||||
for (int i = 0; i < cachedAll.Count; i++)
|
||||
{
|
||||
var item = cachedAll[i];
|
||||
if (item == null) continue;
|
||||
if (item.name.StartsWith(prefix))
|
||||
{
|
||||
dlcDataSO = item;
|
||||
ApplyDlcData(item);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string NormalizeResourcesPath(string path)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
string p = path.Replace("\\", "/");
|
||||
int idx = p.IndexOf("Resources/", System.StringComparison.OrdinalIgnoreCase);
|
||||
if (idx >= 0)
|
||||
{
|
||||
p = p.Substring(idx + "Resources/".Length);
|
||||
}
|
||||
return p.Trim('/');
|
||||
}
|
||||
|
||||
private static IEnumerator BuildCacheIfNeeded(string runtimeFolder)
|
||||
{
|
||||
if (cacheBuilt)
|
||||
{
|
||||
yield break;
|
||||
}
|
||||
if (cacheBuilding)
|
||||
{
|
||||
while (!cacheBuilt)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
yield break;
|
||||
}
|
||||
|
||||
cacheBuilding = true;
|
||||
cachedById.Clear();
|
||||
cachedAll.Clear();
|
||||
cachedFolder = NormalizeResourcesPath(runtimeFolder);
|
||||
|
||||
// allow one frame before heavy load
|
||||
yield return null;
|
||||
|
||||
dlcData[] arr = null;
|
||||
if (!string.IsNullOrEmpty(cachedFolder))
|
||||
{
|
||||
arr = Resources.LoadAll<dlcData>(cachedFolder);
|
||||
}
|
||||
if (arr == null || arr.Length == 0)
|
||||
{
|
||||
arr = Resources.LoadAll<dlcData>("");
|
||||
}
|
||||
|
||||
if (arr != null)
|
||||
{
|
||||
for (int i = 0; i < arr.Length; i++)
|
||||
{
|
||||
var so = arr[i];
|
||||
if (so == null) continue;
|
||||
cachedAll.Add(so);
|
||||
if (!cachedById.ContainsKey(so.dlcID))
|
||||
{
|
||||
cachedById.Add(so.dlcID, so);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cacheBuilt = true;
|
||||
cacheBuilding = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,26 +10,26 @@ public class dlcData : ScriptableObject
|
||||
[Header("DLC֮ID")]
|
||||
public int dlcID;
|
||||
|
||||
[Header("DLC名称")]
|
||||
[Header("DLC����")]
|
||||
public string dlcName;
|
||||
|
||||
[Header("DLC出品人")]
|
||||
[Header("DLC��Ʒ��")]
|
||||
public string dlcProducer;
|
||||
|
||||
[Header("DLC是否已解锁")]
|
||||
[Header("DLC�Ƿ��ѽ���")]
|
||||
public bool dlcIsUnlocked;
|
||||
|
||||
[Header("DLC简介")]
|
||||
[Header("DLC���")]
|
||||
[TextArea(3,10)]
|
||||
public string dlcDescription;
|
||||
|
||||
[Header("DLC发行日期 yyyy-mm-dd")]
|
||||
[Header("DLC�������� yyyy-mm-dd")]
|
||||
public string dlcPublishDate;
|
||||
|
||||
[Header("DLC所含曲目(ScriptableObjects)")]
|
||||
[Header("DLC������Ŀ��ScriptableObjects��")]
|
||||
public List<SongData> songList = new List<SongData>();
|
||||
|
||||
[Header("本DLC结算音乐")]
|
||||
[Tooltip("在结算界面播放的背景音乐AudioClip")]
|
||||
[Header("��DLC��������")]
|
||||
[Tooltip("�ڽ�����沥�ŵı�������AudioClip")]
|
||||
public AudioClip settlementMusic;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class loadDlcListPrefab : MonoBehaviour
|
||||
@@ -106,14 +107,27 @@ public class loadDlcListPrefab : MonoBehaviour
|
||||
var rt = dlc_scContent.GetComponent<RectTransform>();
|
||||
if (rt != null) UnityEngine.UI.LayoutRebuilder.ForceRebuildLayoutImmediate(rt);
|
||||
|
||||
// After all buttons are instantiated, have each dlcButton resolve its dlcData (deferred lookup)
|
||||
var allButtons = dlc_scContent.GetComponentsInChildren<dlcButton>(true);
|
||||
foreach (var b in allButtons)
|
||||
StartCoroutine(ResolveAndRestore(allButtons));
|
||||
}
|
||||
|
||||
private IEnumerator ResolveAndRestore(dlcButton[] allButtons)
|
||||
{
|
||||
if (allButtons != null)
|
||||
{
|
||||
if (b != null)
|
||||
b.ResolveDlcData();
|
||||
for (int i = 0; i < allButtons.Length; i++)
|
||||
{
|
||||
var b = allButtons[i];
|
||||
if (b != null)
|
||||
{
|
||||
yield return b.ResolveDlcDataAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Let layout and any fades settle for a frame
|
||||
yield return null;
|
||||
|
||||
// Restore last selected DLC button from PlayerPrefs and simulate a click on it
|
||||
int savedIndex = PlayerPrefs.GetInt("dlc_selected_index", 0);
|
||||
if (allButtons != null && allButtons.Length > 0)
|
||||
@@ -138,4 +152,5 @@ public class loadDlcListPrefab : MonoBehaviour
|
||||
Debug.LogWarning("loadDlcListPrefab: no dlc buttons found after RefreshUI");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,12 +3,13 @@ using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityEngine.SceneManagement;
|
||||
using System.Collections;
|
||||
using DG.Tweening;
|
||||
|
||||
public class selected_songInfo : MonoBehaviour
|
||||
{
|
||||
public Image t_songCoverImage;
|
||||
public Image btm_songCoverImage;
|
||||
[Header("极简信息")]
|
||||
[Header("������Ϣ")]
|
||||
public Text songNameText;
|
||||
public Text currentDifficulty;
|
||||
public Text sumScore_thisDifficulty;
|
||||
@@ -17,22 +18,22 @@ public class selected_songInfo : MonoBehaviour
|
||||
|
||||
public Image c_DifficultyImage;
|
||||
public Image c_imageMask;
|
||||
[Header("分级颜色")]
|
||||
[Header("�ּ���ɫ")]
|
||||
public Color _0to5d5;
|
||||
public Color _5d5to11;
|
||||
public Color _11to16d5;
|
||||
public Color _16d5to22;
|
||||
public Color _equal22;
|
||||
|
||||
[Header("对应的难度按钮")]
|
||||
[Header("��Ӧ���ѶȰ�ť")]
|
||||
public List<Button> difficultyButtons = new List<Button>();
|
||||
[Header("对应的难度文本")]
|
||||
[Header("��Ӧ���Ѷ��ı�")]
|
||||
public List<Text> difficultyTexts = new List<Text>();
|
||||
[Header("enter detail page")]
|
||||
public Button enterDetailPageButton;
|
||||
[Header("quick enter game play")]
|
||||
public Button quickEnter_gamePlay;
|
||||
[Header("指定image背景色")]
|
||||
[Header("ָ��image����ɫ")]
|
||||
public Sprite buttons_bgImage;
|
||||
[Header("black mask")]
|
||||
public Image blackMaskImage;
|
||||
@@ -40,41 +41,63 @@ public class selected_songInfo : MonoBehaviour
|
||||
// store the original sprites so we don't overwrite the designer's setup
|
||||
private List<Sprite> originalButtonSprites = new List<Sprite>();
|
||||
|
||||
[Header("Switch Animations")]
|
||||
[SerializeField] bool play_SongSwitch_Anim = true;
|
||||
[SerializeField] RectTransform songInfo_Root;
|
||||
[SerializeField] float songSwitch_Time = 0.22f;
|
||||
[SerializeField] float songSwitch_Move = 30f;
|
||||
[SerializeField] Ease songSwitch_Ease = Ease.OutCubic;
|
||||
[SerializeField] bool play_DifficultySwitch_Anim = true;
|
||||
[SerializeField] float diffSwitch_Punch = 0.06f;
|
||||
[SerializeField] float diffSwitch_Punch_Time = 0.18f;
|
||||
[SerializeField] float diffSwitch_Text_Fade = 0.08f;
|
||||
[SerializeField] bool switch_Use_Unscaled = true;
|
||||
|
||||
private CanvasGroup songInfo_Canvas;
|
||||
private Vector2 songInfo_BasePos;
|
||||
private bool songInfo_BaseCached;
|
||||
private int lastSongId = -1;
|
||||
|
||||
private static void LogVerbose(string message)
|
||||
{
|
||||
if (GameConfig.verboseLogs) Debug.LogWarning(message);
|
||||
}
|
||||
|
||||
void Awake()
|
||||
{
|
||||
Debug.LogWarning("selected_songInfo.Awake called");
|
||||
LogVerbose("selected_songInfo.Awake called");
|
||||
}
|
||||
|
||||
void OnEnable()
|
||||
{
|
||||
Debug.LogWarning("selected_songInfo.OnEnable called");
|
||||
LogVerbose("selected_songInfo.OnEnable called");
|
||||
// register listeners here to ensure binding even if Start wasn't called yet
|
||||
if (enterDetailPageButton != null)
|
||||
{
|
||||
enterDetailPageButton.onClick.RemoveListener(OnEnterDetailPageClicked);
|
||||
enterDetailPageButton.onClick.AddListener(OnEnterDetailPageClicked);
|
||||
Debug.LogWarning("enterDetailPageButton listener added");
|
||||
LogVerbose("enterDetailPageButton listener added");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("enterDetailPageButton is null in OnEnable");
|
||||
LogVerbose("enterDetailPageButton is null in OnEnable");
|
||||
}
|
||||
|
||||
if (quickEnter_gamePlay != null)
|
||||
{
|
||||
quickEnter_gamePlay.onClick.RemoveListener(OnQuickEnterClicked);
|
||||
quickEnter_gamePlay.onClick.AddListener(OnQuickEnterClicked);
|
||||
Debug.LogWarning("quickEnter_gamePlay listener added");
|
||||
LogVerbose("quickEnter_gamePlay listener added");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("quickEnter_gamePlay is null in OnEnable");
|
||||
LogVerbose("quickEnter_gamePlay is null in OnEnable");
|
||||
}
|
||||
}
|
||||
|
||||
void OnDisable()
|
||||
{
|
||||
Debug.LogWarning("selected_songInfo.OnDisable called");
|
||||
LogVerbose("selected_songInfo.OnDisable called");
|
||||
if (enterDetailPageButton != null)
|
||||
{
|
||||
enterDetailPageButton.onClick.RemoveListener(OnEnterDetailPageClicked);
|
||||
@@ -87,14 +110,14 @@ public class selected_songInfo : MonoBehaviour
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
Debug.LogWarning("selected_songInfo.OnDestroy called");
|
||||
LogVerbose("selected_songInfo.OnDestroy called");
|
||||
// ensure we remove sceneLoaded subscription if still present
|
||||
SceneManager.sceneLoaded -= OnSceneLoadedAfterQuickEnter;
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
Debug.LogWarning("selected_songInfo.Start called");
|
||||
LogVerbose("selected_songInfo.Start called");
|
||||
|
||||
// ensure black mask is transparent and inactive at start
|
||||
if (blackMaskImage != null)
|
||||
@@ -137,8 +160,8 @@ public class selected_songInfo : MonoBehaviour
|
||||
UpdateSelectedSongDisplay();
|
||||
|
||||
// Diagnostic: confirm Start ran and key refs
|
||||
Debug.LogWarning($"selected_songInfo.Start: quickEnter_gamePlay is {(quickEnter_gamePlay == null ? "NULL" : "ASSIGNED")}, enterDetail assigned={(enterDetailPageButton == null ? "NULL" : "ASSIGNED")}, blackMask assigned={(blackMaskImage == null ? "NULL" : "ASSIGNED")}");
|
||||
Debug.LogWarning($"selected_songInfo.Start: SongDataHolder.SelectedSongData is {(SongDataHolder.SelectedSongData == null ? "NULL" : SongDataHolder.SelectedSongData.songName)}");
|
||||
LogVerbose($"selected_songInfo.Start: quickEnter_gamePlay is {(quickEnter_gamePlay == null ? "NULL" : "ASSIGNED")}, enterDetail assigned={(enterDetailPageButton == null ? "NULL" : "ASSIGNED")}, blackMask assigned={(blackMaskImage == null ? "NULL" : "ASSIGNED")}");
|
||||
LogVerbose($"selected_songInfo.Start: SongDataHolder.SelectedSongData is {(SongDataHolder.SelectedSongData == null ? "NULL" : SongDataHolder.SelectedSongData.songName)}");
|
||||
}
|
||||
|
||||
public void UpdateSelectedSongDisplay()
|
||||
@@ -270,6 +293,8 @@ public class selected_songInfo : MonoBehaviour
|
||||
int enterTimes = song.game_enterTimes;
|
||||
total_gameTime.text = enterTimes.ToString();
|
||||
}
|
||||
|
||||
TryPlaySongSwitchAnim(song.songID);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -286,7 +311,7 @@ public class selected_songInfo : MonoBehaviour
|
||||
}
|
||||
if (songNameText != null)
|
||||
{
|
||||
songNameText.text = "未选择歌曲";
|
||||
songNameText.text = "δѡ�����";
|
||||
}
|
||||
|
||||
// restore original difficulty button backgrounds and text colors
|
||||
@@ -294,6 +319,7 @@ public class selected_songInfo : MonoBehaviour
|
||||
|
||||
if (sumScore_thisDifficulty != null) sumScore_thisDifficulty.text = "0";
|
||||
if (total_gameTime != null) total_gameTime.text = "0";
|
||||
lastSongId = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,6 +392,7 @@ public class selected_songInfo : MonoBehaviour
|
||||
|
||||
// refresh displayed song info so currentDifficulty / difficulty bar update to new difficulty
|
||||
UpdateSelectedSongDisplay();
|
||||
PlayDifficultySwitchAnim(index);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -373,11 +400,95 @@ public class selected_songInfo : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureSongInfoRoot()
|
||||
{
|
||||
if (songInfo_Root == null)
|
||||
{
|
||||
songInfo_Root = transform as RectTransform;
|
||||
}
|
||||
if (songInfo_Root == null) return;
|
||||
if (songInfo_Canvas == null || songInfo_Canvas.gameObject != songInfo_Root.gameObject)
|
||||
{
|
||||
songInfo_Canvas = songInfo_Root.GetComponent<CanvasGroup>();
|
||||
if (songInfo_Canvas == null)
|
||||
{
|
||||
songInfo_Canvas = songInfo_Root.gameObject.AddComponent<CanvasGroup>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void TryPlaySongSwitchAnim(int songId)
|
||||
{
|
||||
if (!play_SongSwitch_Anim)
|
||||
{
|
||||
lastSongId = songId;
|
||||
return;
|
||||
}
|
||||
if (lastSongId == songId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lastSongId = songId;
|
||||
EnsureSongInfoRoot();
|
||||
if (songInfo_Root == null || songInfo_Canvas == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
songInfo_BasePos = songInfo_Root.anchoredPosition;
|
||||
songInfo_BaseCached = true;
|
||||
songInfo_Root.DOKill();
|
||||
songInfo_Canvas.DOKill();
|
||||
songInfo_Root.anchoredPosition = songInfo_BasePos + new Vector2(-songSwitch_Move, 0f);
|
||||
songInfo_Canvas.alpha = 0f;
|
||||
Sequence seq = DOTween.Sequence().SetUpdate(switch_Use_Unscaled);
|
||||
seq.Join(songInfo_Root.DOAnchorPos(songInfo_BasePos, songSwitch_Time).SetEase(songSwitch_Ease));
|
||||
seq.Join(songInfo_Canvas.DOFade(1f, songSwitch_Time));
|
||||
}
|
||||
|
||||
private void PlayDifficultySwitchAnim(int index)
|
||||
{
|
||||
if (!play_DifficultySwitch_Anim)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (difficultyButtons != null && index >= 0 && index < difficultyButtons.Count)
|
||||
{
|
||||
var btn = difficultyButtons[index];
|
||||
if (btn != null)
|
||||
{
|
||||
Transform t = btn.transform;
|
||||
t.DOKill();
|
||||
t.localScale = Vector3.one;
|
||||
t.DOPunchScale(Vector3.one * diffSwitch_Punch, diffSwitch_Punch_Time, 6, 0.7f)
|
||||
.SetUpdate(switch_Use_Unscaled);
|
||||
}
|
||||
}
|
||||
FlashGraphic(currentDifficulty);
|
||||
FlashGraphic(sumScore_thisDifficulty);
|
||||
if (c_DifficultyImage != null)
|
||||
{
|
||||
FlashGraphic(c_DifficultyImage);
|
||||
}
|
||||
}
|
||||
|
||||
private void FlashGraphic(Graphic g)
|
||||
{
|
||||
if (g == null) return;
|
||||
g.DOKill();
|
||||
Color baseColor = g.color;
|
||||
float baseAlpha = baseColor.a <= 0f ? 1f : baseColor.a;
|
||||
baseColor.a = baseAlpha;
|
||||
g.color = baseColor;
|
||||
Sequence seq = DOTween.Sequence().SetUpdate(switch_Use_Unscaled);
|
||||
seq.Append(g.DOFade(Mathf.Clamp01(baseAlpha * 0.35f), diffSwitch_Text_Fade));
|
||||
seq.Append(g.DOFade(baseAlpha, diffSwitch_Text_Fade));
|
||||
}
|
||||
|
||||
public void OnEnterDetailPageClicked()
|
||||
{
|
||||
if (SongDataHolder.SelectedSongData != null)
|
||||
{
|
||||
SceneManager.LoadScene("Songs_Select");
|
||||
StartCoroutine(LoadSceneAsync("Songs_Select"));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -385,6 +496,15 @@ public class selected_songInfo : MonoBehaviour
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator LoadSceneAsync(string sceneName)
|
||||
{
|
||||
AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(sceneName);
|
||||
while (!asyncLoad.isDone)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnQuickEnterClicked()
|
||||
{
|
||||
// use SongData from holder or SongButton; ensure selection exists
|
||||
@@ -392,7 +512,7 @@ public class selected_songInfo : MonoBehaviour
|
||||
if (sd == null) sd = SongDataHolder.SelectedSongData;
|
||||
if (sd == null)
|
||||
{
|
||||
Debug.LogWarning("No song selected - cannot quick enter gameplay.");
|
||||
LogVerbose("No song selected - cannot quick enter gameplay.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -404,7 +524,7 @@ public class selected_songInfo : MonoBehaviour
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.LogWarning($"QuickEnter clicked, selected song: {sd.songName} id={sd.songID} difficulty={sd.thisLevel_selectedDifficultyID}");
|
||||
LogVerbose($"QuickEnter clicked, selected song: {sd.songName} id={sd.songID} difficulty={sd.thisLevel_selectedDifficultyID}");
|
||||
|
||||
// pass selection to BeatmapManager pending fields so newly loaded scene picks it up
|
||||
BeatmapManager.SetPendingSong(sd, sd.thisLevel_selectedDifficultyID);
|
||||
@@ -420,7 +540,7 @@ public class selected_songInfo : MonoBehaviour
|
||||
|
||||
private IEnumerator QuickEnterSequence()
|
||||
{
|
||||
Debug.LogWarning("QuickEnterSequence started: beginning fade");
|
||||
LogVerbose("QuickEnterSequence started: beginning fade");
|
||||
// Fade black mask in over 0.25 seconds
|
||||
float duration = 0.25f;
|
||||
if (blackMaskImage != null)
|
||||
@@ -455,7 +575,7 @@ public class selected_songInfo : MonoBehaviour
|
||||
blackMaskImage.color = c;
|
||||
}
|
||||
|
||||
Debug.LogWarning("Fade complete, loading gameplay scene...");
|
||||
LogVerbose("Fade complete, loading gameplay scene...");
|
||||
// after black screen, load gameplay scene asynchronously and wait for completion
|
||||
SceneManager.sceneLoaded += OnSceneLoadedAfterQuickEnter;
|
||||
var asyncOp = SceneManager.LoadSceneAsync("gamePlay_gamePlay");
|
||||
@@ -478,8 +598,8 @@ public class selected_songInfo : MonoBehaviour
|
||||
|
||||
private SongData FindSongDataFromSelectedButton()
|
||||
{
|
||||
var allButtons = FindObjectsOfType<SongButton>();
|
||||
Debug.LogWarning($"FindSongDataFromSelectedButton: found {allButtons.Length} SongButton instances");
|
||||
var allButtons = Object.FindObjectsByType<SongButton>(FindObjectsInactive.Exclude, FindObjectsSortMode.InstanceID);
|
||||
LogVerbose($"FindSongDataFromSelectedButton: found {allButtons.Length} SongButton instances");
|
||||
foreach (var sb in allButtons)
|
||||
{
|
||||
if (sb == null) continue;
|
||||
@@ -490,7 +610,7 @@ public class selected_songInfo : MonoBehaviour
|
||||
Image img = null;
|
||||
if (field != null) img = field.GetValue(sb) as Image;
|
||||
float alpha = img != null ? img.color.a : -1f;
|
||||
Debug.LogWarning($"SongButton id field value for '{sb.name}': selected_boarder alpha={alpha}");
|
||||
LogVerbose($"SongButton id field value for '{sb.name}': selected_boarder alpha={alpha}");
|
||||
|
||||
if (img != null && img.color.a > 0.5f)
|
||||
{
|
||||
@@ -501,7 +621,7 @@ public class selected_songInfo : MonoBehaviour
|
||||
var soObj = soField.GetValue(sb);
|
||||
if (soObj != null && soObj is SongData)
|
||||
{
|
||||
Debug.LogWarning($"Selected SongButton has thisSong_so assigned: {((SongData)soObj).songName}");
|
||||
LogVerbose($"Selected SongButton has thisSong_so assigned: {((SongData)soObj).songName}");
|
||||
return soObj as SongData;
|
||||
}
|
||||
}
|
||||
@@ -511,11 +631,11 @@ public class selected_songInfo : MonoBehaviour
|
||||
if (idField != null)
|
||||
{
|
||||
int id = (int)idField.GetValue(sb);
|
||||
Debug.LogWarning($"Selected SongButton id = {id}");
|
||||
LogVerbose($"Selected SongButton id = {id}");
|
||||
var sd = SongDataLibrary.Instance != null ? SongDataLibrary.Instance.GetSongDataByID(id) : null;
|
||||
if (sd != null)
|
||||
{
|
||||
Debug.LogWarning($"Found SongData by id: {sd.songName}");
|
||||
LogVerbose($"Found SongData by id: {sd.songName}");
|
||||
return sd;
|
||||
}
|
||||
}
|
||||
@@ -523,10 +643,10 @@ public class selected_songInfo : MonoBehaviour
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Debug.LogWarning("Exception while inspecting SongButton: " + ex.Message);
|
||||
LogVerbose("Exception while inspecting SongButton: " + ex.Message);
|
||||
}
|
||||
}
|
||||
Debug.LogWarning("FindSongDataFromSelectedButton: no selected SongButton found");
|
||||
LogVerbose("FindSongDataFromSelectedButton: no selected SongButton found");
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -566,7 +686,7 @@ public class selected_songInfo : MonoBehaviour
|
||||
|
||||
if (selected == null)
|
||||
{
|
||||
Debug.LogWarning("OnSceneLoadedAfterQuickEnter: SelectedSongData is null");
|
||||
LogVerbose("OnSceneLoadedAfterQuickEnter: SelectedSongData is null");
|
||||
SceneManager.sceneLoaded -= OnSceneLoadedAfterQuickEnter;
|
||||
// allow this object to be destroyed now
|
||||
Destroy(this.gameObject);
|
||||
@@ -574,26 +694,26 @@ public class selected_songInfo : MonoBehaviour
|
||||
}
|
||||
|
||||
// find managers in the new scene
|
||||
var beatmapManager = FindObjectOfType<BeatmapManager>();
|
||||
var gameManager = FindObjectOfType<GameManager>();
|
||||
var beatmapManager = Object.FindAnyObjectByType<BeatmapManager>();
|
||||
var gameManager = Object.FindAnyObjectByType<GameManager>();
|
||||
|
||||
Debug.LogWarning($"selected song: {selected.songName} (id {selected.songID}), difficulty {selected.thisLevel_selectedDifficultyID}");
|
||||
LogVerbose($"selected song: {selected.songName} (id {selected.songID}), difficulty {selected.thisLevel_selectedDifficultyID}");
|
||||
|
||||
// get chart TextAsset from SongData for current selected difficulty
|
||||
TextAsset chartAsset = selected.GetChartFile(selected.thisLevel_selectedDifficultyID);
|
||||
if (chartAsset == null)
|
||||
{
|
||||
Debug.LogWarning($"Chart file for difficulty {selected.thisLevel_selectedDifficultyID} not found on SongData {selected.songName}");
|
||||
LogVerbose($"Chart file for difficulty {selected.thisLevel_selectedDifficultyID} not found on SongData {selected.songName}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"Chart asset found, size={chartAsset.text?.Length ?? 0} chars");
|
||||
LogVerbose($"Chart asset found, size={chartAsset.text?.Length ?? 0} chars");
|
||||
}
|
||||
|
||||
// parse beatmap only and assign music, but DO NOT start spawning until player starts
|
||||
if (beatmapManager != null && chartAsset != null)
|
||||
{
|
||||
Debug.LogWarning("Parsing chart JSON via BeatmapManager.ParseJsonOnly");
|
||||
LogVerbose("Parsing chart JSON via BeatmapManager.ParseJsonOnly");
|
||||
bool parsed = false;
|
||||
try
|
||||
{
|
||||
@@ -601,21 +721,21 @@ public class selected_songInfo : MonoBehaviour
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Debug.LogWarning("Exception during ParseJsonOnly: " + ex.Message + "\n" + ex.StackTrace);
|
||||
LogVerbose("Exception during ParseJsonOnly: " + ex.Message + "\n" + ex.StackTrace);
|
||||
}
|
||||
Debug.LogWarning($"ParseJsonOnly returned {parsed}");
|
||||
LogVerbose($"ParseJsonOnly returned {parsed}");
|
||||
if (!parsed)
|
||||
{
|
||||
Debug.LogWarning("Failed to parse chart JSON from SongData chart file.");
|
||||
LogVerbose("Failed to parse chart JSON from SongData chart file.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"Beatmap parsed: beatmap is {(beatmapManager.beatmap != null ? "NOT null" : "null")}, parsedMusicFile={beatmapManager.parsedMusicFile}, globalDelaySeconds={beatmapManager.globalDelaySeconds}");
|
||||
LogVerbose($"Beatmap parsed: beatmap is {(beatmapManager.beatmap != null ? "NOT null" : "null")}, parsedMusicFile={beatmapManager.parsedMusicFile}, globalDelaySeconds={beatmapManager.globalDelaySeconds}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (beatmapManager == null) Debug.LogWarning("BeatmapManager not found in gameplay scene");
|
||||
if (beatmapManager == null) LogVerbose("BeatmapManager not found in gameplay scene");
|
||||
}
|
||||
|
||||
// assign audio clip to GameManager.musicSource if available
|
||||
@@ -639,7 +759,7 @@ public class selected_songInfo : MonoBehaviour
|
||||
Debug.LogWarning("Failed to Play() for warmup: " + ex.Message);
|
||||
}
|
||||
|
||||
Debug.LogWarning("Assigned SongData.audioFile to GameManager.musicSource.clip (playOnAwake disabled)");
|
||||
LogVerbose("Assigned SongData.audioFile to GameManager.musicSource.clip (playOnAwake disabled)");
|
||||
|
||||
// Request PauseManager-driven pause (centralized)
|
||||
RequestPauseManagerPause();
|
||||
@@ -649,7 +769,7 @@ public class selected_songInfo : MonoBehaviour
|
||||
// try to load by parsedMusicFile similar to pressStart normal mode
|
||||
if (gameManager.musicSource != null && beatmapManager != null && !string.IsNullOrEmpty(beatmapManager.parsedMusicFile))
|
||||
{
|
||||
Debug.LogWarning($"Attempting Resources.Load for audio: {beatmapManager.parsedMusicFile}");
|
||||
LogVerbose($"Attempting Resources.Load for audio: {beatmapManager.parsedMusicFile}");
|
||||
var ac = Resources.Load<AudioClip>(beatmapManager.parsedMusicFile);
|
||||
if (ac != null)
|
||||
{
|
||||
@@ -660,25 +780,25 @@ public class selected_songInfo : MonoBehaviour
|
||||
{
|
||||
gameManager.musicSource.mute = true;
|
||||
gameManager.musicSource.Play();
|
||||
Debug.LogWarning("Warmed audio playback (muted) after Resources.Load");
|
||||
LogVerbose("Warmed audio playback (muted) after Resources.Load");
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Debug.LogWarning("Failed to Play() for warmup after Resources.Load: " + ex.Message);
|
||||
LogVerbose("Failed to Play() for warmup after Resources.Load: " + ex.Message);
|
||||
}
|
||||
|
||||
Debug.LogWarning("Loaded audio via Resources.Load(parsedMusicFile) and disabled playOnAwake");
|
||||
LogVerbose("Loaded audio via Resources.Load(parsedMusicFile) and disabled playOnAwake");
|
||||
|
||||
RequestPauseManagerPause();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"Resources.Load failed for '{beatmapManager.parsedMusicFile}'");
|
||||
LogVerbose($"Resources.Load failed for '{beatmapManager.parsedMusicFile}'");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("No audio assigned: selected.audioFile null and parsedMusicFile empty or musicSource missing");
|
||||
LogVerbose("No audio assigned: selected.audioFile null and parsedMusicFile empty or musicSource missing");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -689,16 +809,16 @@ public class selected_songInfo : MonoBehaviour
|
||||
|
||||
// Start coroutine to wait for player input (Space) to begin playback and spawning
|
||||
// Use a safe host for coroutine in case this MonoBehaviour is destroyed unexpectedly
|
||||
var pauseMgr = PauseManager.Instance ?? FindObjectOfType<PauseManager>();
|
||||
var pauseMgr = PauseManager.Instance != null ? PauseManager.Instance : Object.FindAnyObjectByType<PauseManager>();
|
||||
MonoBehaviour coroutineHost = (pauseMgr as MonoBehaviour) ?? (gameManager as MonoBehaviour) ?? (beatmapManager as MonoBehaviour) ?? this;
|
||||
if (coroutineHost != null)
|
||||
{
|
||||
Debug.LogWarning("Starting WaitForPlayerStartAndBegin coroutine on host: " + coroutineHost.name);
|
||||
LogVerbose("Starting WaitForPlayerStartAndBegin coroutine on host: " + coroutineHost.name);
|
||||
coroutineHost.StartCoroutine(WaitForPlayerStartAndBegin(beatmapManager, gameManager));
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("No valid coroutine host found to start WaitForPlayerStartAndBegin.");
|
||||
LogVerbose("No valid coroutine host found to start WaitForPlayerStartAndBegin.");
|
||||
}
|
||||
|
||||
// unsubscribe from sceneLoaded
|
||||
@@ -707,24 +827,24 @@ public class selected_songInfo : MonoBehaviour
|
||||
|
||||
private IEnumerator WaitForPlayerStartAndBegin(BeatmapManager beatmapManager, GameManager gameManager)
|
||||
{
|
||||
Debug.LogWarning("Waiting for player to press Space to start playback...");
|
||||
LogVerbose("Waiting for player to press Space to start playback...");
|
||||
// Wait until player presses Space
|
||||
while (!Input.GetKeyDown(KeyCode.Space))
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
Debug.LogWarning("Player pressed Space. Preparing to start playback.");
|
||||
LogVerbose("Player pressed Space. Preparing to start playback.");
|
||||
|
||||
// wait for NotePool prewarm to complete (block until finished to avoid hitch)
|
||||
if (NotePool.Instance != null)
|
||||
{
|
||||
Debug.LogWarning("Waiting for NotePool prewarm to finish (blocking)...");
|
||||
LogVerbose("Waiting for NotePool prewarm to finish (blocking)...");
|
||||
while (!NotePool.Instance.IsPrewarmed)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
Debug.LogWarning("NotePool prewarm completed.");
|
||||
LogVerbose("NotePool prewarm completed.");
|
||||
}
|
||||
|
||||
// ensure audio has been warmed (attempt play muted if not already playing)
|
||||
@@ -739,18 +859,18 @@ public class selected_songInfo : MonoBehaviour
|
||||
}
|
||||
|
||||
// Prewarm particle systems via AnimationController to avoid first-play hitch
|
||||
var anim = AnimationController.Global ?? FindObjectOfType<AnimationController>();
|
||||
var anim = AnimationController.Global != null ? AnimationController.Global : Object.FindAnyObjectByType<AnimationController>();
|
||||
if (anim != null)
|
||||
{
|
||||
Debug.LogWarning("Starting AnimationController particle prewarm (will wait until complete)...");
|
||||
LogVerbose("Starting AnimationController particle prewarm (will wait until complete)...");
|
||||
// yield until the prewarm completes
|
||||
yield return StartCoroutine(anim.PrewarmParticlesRoutine(2));
|
||||
Debug.LogWarning("AnimationController particle prewarm complete.");
|
||||
LogVerbose("AnimationController particle prewarm complete.");
|
||||
}
|
||||
|
||||
// Unpause via PauseManager
|
||||
var pauseMgr = PauseManager.Instance ?? FindObjectOfType<PauseManager>();
|
||||
pauseMgr?.Pause(false);
|
||||
var pauseMgr = PauseManager.Instance != null ? PauseManager.Instance : Object.FindAnyObjectByType<PauseManager>();
|
||||
if (pauseMgr != null) pauseMgr.Pause(false);
|
||||
|
||||
// small buffer to avoid hitching immediately after unpause: wait configured delay from GameManager
|
||||
// Use scaled WaitForSeconds so PauseManager (Escape) will pause the countdown
|
||||
@@ -761,12 +881,12 @@ public class selected_songInfo : MonoBehaviour
|
||||
// Start spawning notes
|
||||
if (beatmapManager != null && beatmapManager.beatmap != null)
|
||||
{
|
||||
Debug.LogWarning("Calling beatmapManager.LoadBeatmap");
|
||||
LogVerbose("Calling beatmapManager.LoadBeatmap");
|
||||
beatmapManager.LoadBeatmap(beatmapManager.beatmap);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("Cannot start beatmap: beatmapManager or beatmap is null.");
|
||||
LogVerbose("Cannot start beatmap: beatmapManager or beatmap is null.");
|
||||
}
|
||||
|
||||
// fade out black mask in gameManager if available
|
||||
@@ -781,14 +901,14 @@ public class selected_songInfo : MonoBehaviour
|
||||
float delay = beatmapManager != null ? beatmapManager.globalDelaySeconds : 0f;
|
||||
if (gameManager.musicSource.clip != null)
|
||||
{
|
||||
Debug.LogWarning($"Starting audio playback with delay {delay}");
|
||||
LogVerbose($"Starting audio playback with delay {delay}");
|
||||
// Use GameManager helper to ensure unmute and start playback reliably
|
||||
try { gameManager.PlayMusicWithDelay(delay); }
|
||||
catch (System.Exception ex) { Debug.LogWarning("Failed to start music via GameManager.PlayMusicWithDelay: " + ex); }
|
||||
catch (System.Exception ex) { LogVerbose("Failed to start music via GameManager.PlayMusicWithDelay: " + ex); }
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("GameManager.musicSource.clip is null; skipping audio playback.");
|
||||
LogVerbose("GameManager.musicSource.clip is null; skipping audio playback.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -809,7 +929,7 @@ public class selected_songInfo : MonoBehaviour
|
||||
Debug.LogWarning($"enterDetailPageButton assigned={(enterDetailPageButton==null?"NULL":"ASSIGNED")}");
|
||||
Debug.LogWarning($"blackMaskImage assigned={(blackMaskImage==null?"NULL":"ASSIGNED")}");
|
||||
Debug.LogWarning($"SongDataHolder.SelectedSongData={(SongDataHolder.SelectedSongData==null?"NULL":SongDataHolder.SelectedSongData.songName)}");
|
||||
var allButtons = FindObjectsOfType<SongButton>();
|
||||
var allButtons = Object.FindObjectsByType<SongButton>(FindObjectsInactive.Exclude, FindObjectsSortMode.InstanceID);
|
||||
Debug.LogWarning($"Found {allButtons.Length} SongButton instances in scene");
|
||||
for (int i = 0; i < allButtons.Length; i++)
|
||||
{
|
||||
@@ -825,16 +945,16 @@ public class selected_songInfo : MonoBehaviour
|
||||
private void RequestPauseManagerPause()
|
||||
{
|
||||
if (pauseRequested) return;
|
||||
var pm = PauseManager.Instance ?? FindObjectOfType<PauseManager>();
|
||||
var pm = PauseManager.Instance != null ? PauseManager.Instance : Object.FindAnyObjectByType<PauseManager>();
|
||||
if (pm != null)
|
||||
{
|
||||
pm.Pause(true);
|
||||
Debug.LogWarning("selected_songInfo: PauseManager.Pause(true) requested (centralized)");
|
||||
LogVerbose("selected_songInfo: PauseManager.Pause(true) requested (centralized)");
|
||||
pauseRequested = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("selected_songInfo: PauseManager not found when requesting pause");
|
||||
LogVerbose("selected_songInfo: PauseManager not found when requesting pause");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user