技能主要更新,修复卡顿并加入动画,以及各种其他更新。
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();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user