存档重构,游戏内容解锁机制;教程完善(未完成)

This commit is contained in:
SoulliesOfficial
2026-07-18 16:51:18 -04:00
parent d48ef1e65e
commit dda354ebb9
123 changed files with 4032 additions and 558 deletions

View File

@@ -51,24 +51,63 @@ namespace Ichni.Menu
public void InitializeList()
{
// FadeOut 通常已经清理过旧 Tab但这里仍保持幂等防止重复初始化时残留旧引用或重复 UI。
ClearSongTabs();
GenerateSongTabs();
if (songItems.Count == 0)
{
// 空 Chapter 是内容异常;运行时只进入安全状态,不访问 songItems[0],也不允许进入游戏。
selectedTab = null;
closestTab = null;
topBound = content.anchoredPosition.y;
bottomBound = content.anchoredPosition.y;
targetPosition = content.anchoredPosition;
MenuManager.instance.songSelectionUIPage.selectedSong = null;
MenuManager.instance.songSelectionUIPage.selectedSave = null;
MenuManager.instance.songSelectionUIPage.difficultySelectionContainer.SetUp(null);
return;
}
Canvas.ForceUpdateCanvases();
topBound = (songItems.Count * 144f + (songItems.Count - 1) * 60f) - 72f; //topBound中144为tab高度60为tab间距72为tab高度的一半
bottomBound = 72f; //bottomBound中72为tab高度的一半
int songIndex = 0;
if (MenuInformationRecorder.instance.songSelectionRecords.TryGetValue(ChapterSelectionManager.instance.currentChapter, out var record))
int preferredDifficultyIndex = 0;
ChapterSelectionUnit currentChapter = ChapterSelectionManager.instance.currentChapter;
MenuInformationRecorder menuInformationRecorder = MenuInformationRecorder.instance;
if (menuInformationRecorder.TryGetRecordOfThisChapter(out SongSelectionRecord record))
{
songIndex = ChapterSelectionManager.instance.currentChapter.songs.FindIndex(song => song.songName == record.song.songName);
}
if (songItems.Count > 0)
{
StartCoroutine(SnapToItem(songItems[songIndex], true));
preferredDifficultyIndex = record.difficultyListIndex;
SongItemData cachedSong = record.song;
bool cacheNeedsRepair = false;
// 优先按对象引用恢复;若缓存来自内容热更新/重建,再按 songName 进行兼容匹配。
songIndex = songItems.FindIndex(item => item != null && item.GetComponent<SongSelectionTab>()?.connectedSong == cachedSong);
if (songIndex < 0 && !string.IsNullOrEmpty(cachedSong?.songName))
{
songIndex = songItems.FindIndex(item => item != null &&
item.GetComponent<SongSelectionTab>()?.connectedSong?.songName == cachedSong.songName);
cacheNeedsRepair = songIndex >= 0;
}
// 缓存歌曲已经被删除或改名时,立即修正缓存;难度由 SnapToItem 内的统一回退机制继续解析。
if (songIndex < 0)
{
songIndex = 0;
cacheNeedsRepair = true;
}
if (cacheNeedsRepair)
{
SongItemData resolvedSong = songItems[songIndex].GetComponent<SongSelectionTab>().connectedSong;
menuInformationRecorder.SetRecordForChapter(currentChapter, resolvedSong, preferredDifficultyIndex);
}
}
StartCoroutine(SnapToItem(songItems[songIndex], true));
closestTab = songItems[songIndex];
targetPosition = content.anchoredPosition;
@@ -181,13 +220,20 @@ namespace Ichni.Menu
{
public void ClearSongTabs()
{
StopAllCoroutines();
foreach (RectTransform item in songItems)
{
Destroy(item.gameObject);
if (item != null)
{
Destroy(item.gameObject);
}
}
songItems.Clear();
selectedTab = null;
closestTab = null;
velocity = Vector2.zero;
isDragging = false;
SnapCoroutine = null;
targetPosition = content.anchoredPosition;
isDuringSnap = false;
}
@@ -195,8 +241,19 @@ namespace Ichni.Menu
public void GenerateSongTabs()
{
ChapterSelectionUnit chapterUnit = ChapterSelectionManager.instance.currentChapter;
if (chapterUnit == null || chapterUnit.songs == null)
{
return;
}
foreach (SongItemData song in chapterUnit.songs)
{
if (song == null)
{
Debug.LogWarning("Skipped an empty song entry while generating song selection tabs.");
continue;
}
SongSelectionTab tab = Instantiate(songItemPrefab, content).GetComponent<SongSelectionTab>();
songItems.Add(tab.GetComponent<RectTransform>());
tab.SetUpTab(song);
@@ -330,4 +387,4 @@ namespace Ichni.Menu
isDuringSnap = false;
}
}
}
}