using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; namespace GameFramework { /// /// 排行榜场景 UI 控制器。 /// 如果当前得分能进入 Top-10,先显示输入名字面板; /// 否则直接显示排行榜。 /// 修复了源项目 ScoringUIController 中 ShowScoringScreen() 被调用两次的 bug。 /// public class ScoringUIController : MonoBehaviour { [Header("Panels")] [SerializeField] GameObject leaderboardPanel; [SerializeField] GameObject newHighScorePanel; [Header("Leaderboard")] [SerializeField] Transform leaderboardContainer; // 包含10个条目的父物体 [SerializeField] Text finalScoreText; // 显示当前局最终得分 [Header("New High Score")] [SerializeField] InputField nameInputField; [SerializeField] Button submitButton; [SerializeField] Button cancelButton; [Header("Navigation")] [SerializeField] Button mainMenuButton; [Header("Audio")] [SerializeField] AudioData submitSFX; [SerializeField] AudioData cancelSFX; void Start() { // 绑定按钮 if (submitButton != null) submitButton.onClick.AddListener(OnSubmitClick); if (cancelButton != null) cancelButton.onClick.AddListener(OnCancelClick); if (mainMenuButton != null) mainMenuButton.onClick.AddListener(OnMainMenuClick); // 初始隐藏所有面板 if (leaderboardPanel != null) leaderboardPanel.SetActive(false); if (newHighScorePanel != null) newHighScorePanel.SetActive(false); // 显示当前最终得分 if (finalScoreText != null && ScoreManager.Instance != null) finalScoreText.text = ScoreManager.Instance.CurrentScore.ToString(); // 判断是否进入排行榜 // 只调用一次——修复源项目的双重调用 bug if (ScoreManager.Instance != null && ScoreManager.Instance.HasNewHighScore) { ShowNewHighScorePanel(); } else { ShowLeaderboard(); } } /// /// 显示新纪录输入面板。 /// void ShowNewHighScorePanel() { if (newHighScorePanel != null) newHighScorePanel.SetActive(true); if (leaderboardPanel != null) leaderboardPanel.SetActive(false); // 自动选中输入框 if (nameInputField != null) { nameInputField.text = ""; nameInputField.ActivateInputField(); } } /// /// 显示排行榜。 /// void ShowLeaderboard() { if (newHighScorePanel != null) newHighScorePanel.SetActive(false); if (leaderboardPanel != null) leaderboardPanel.SetActive(true); UpdateLeaderboardDisplay(); // 选中主菜单按钮(键盘导航用) if (mainMenuButton != null) mainMenuButton.Select(); } /// /// 更新排行榜显示。 /// 遍历 leaderboardContainer 下的子物体,设置排名/得分/名字。 /// 每个条目子物体需要有三个 Text 组件,分别在 Rank/Score/Name 子物体上。 /// void UpdateLeaderboardDisplay() { if (ScoreManager.Instance == null) return; if (leaderboardContainer == null) return; var data = ScoreManager.Instance.LoadPlayerScoreData(); int count = Mathf.Min(data.list.Count, leaderboardContainer.childCount); for (int i = 0; i < leaderboardContainer.childCount; i++) { Transform entry = leaderboardContainer.GetChild(i); bool hasData = i < data.list.Count; // 查找条目下的三个 Text Text rankText = FindTextByName(entry, "Rank"); Text scoreText = FindTextByName(entry, "Score"); Text nameText = FindTextByName(entry, "Name"); if (hasData) { var score = data.list[i]; if (rankText != null) rankText.text = $"{i + 1}."; if (scoreText != null) scoreText.text = score.score.ToString(); if (nameText != null) nameText.text = score.playerName; entry.gameObject.SetActive(true); } else { if (rankText != null) rankText.text = $"{i + 1}."; if (scoreText != null) scoreText.text = "---"; if (nameText != null) nameText.text = "---"; entry.gameObject.SetActive(true); } } } /// /// 在子物体中按名称查找 Text 组件。 /// Text FindTextByName(Transform parent, string name) { Transform t = parent.Find(name); if (t != null) return t.GetComponent(); // 如果条目本身就是单个 Text(没有子结构),返回自身 return parent.GetComponent(); } #region Button Handlers void OnSubmitClick() { string playerName = ""; if (nameInputField != null) playerName = nameInputField.text; if (string.IsNullOrEmpty(playerName)) playerName = "Player"; if (ScoreManager.Instance != null) ScoreManager.Instance.SavePlayerScore(playerName); if (AudioManager.Instance != null && submitSFX != null) AudioManager.Instance.PlaySFX(submitSFX); ShowLeaderboard(); } void OnCancelClick() { // 取消 = 用默认名保存后显示排行榜 if (ScoreManager.Instance != null) ScoreManager.Instance.SavePlayerScore("Player"); if (AudioManager.Instance != null && cancelSFX != null) AudioManager.Instance.PlaySFX(cancelSFX); ShowLeaderboard(); } void OnMainMenuClick() { if (SceneLoader.Instance != null) SceneLoader.Instance.LoadMainMenuScene(); } #endregion } }