求助:如何在LibGDX中用Preferences实现含用户名与分数的排行榜
嘿,我懂你现在的困境——之前只做了显示单一最高分的功能,现在想改成带用户名的排行榜,还打算用Preferences来实现,结果尝试关联用户名和分数的时候卡壳了对吧?别着急,我给你一步步捋清楚怎么搞定这个需求,结合代码示例来帮你落地。
用Preferences实现带用户名的排行榜
核心思路是把用户-分数的配对数据以结构化的方式存在Preferences里,再做排序和显示处理,具体步骤如下:
1. 设计Preferences的存储结构
Preferences是键值对存储,我们不能只存单个分数,得用一组关联的键来保存多条记录:
- 用
highscore_count记录当前排行榜的总条数(比如我们设定最多存5条高分) - 每条记录对应两个键:
highscore_索引_name存用户名,highscore_索引_score存对应分数(比如highscore_0_name、highscore_0_score对应第一条记录)
2. 编写高分管理核心方法
下面以Unity为例写核心逻辑(其他引擎的Preferences API类似,只需替换对应方法):
using UnityEngine; using System.Collections.Generic; public class HighscoreManager : MonoBehaviour { // 排行榜最多保存的条数 private const int MAX_HIGHSCORE_ENTRIES = 5; // 记录总条数的键名 private const string HIGHSCORE_COUNT_KEY = "highscore_total"; // 对外暴露的添加高分方法 public void AddNewHighscore(string username, int currentScore) { // 先获取当前所有已存的高分记录 List<(string name, int score)> highscoreList = GetAllHighscores(); // 添加新的用户-分数配对 highscoreList.Add((username, currentScore)); // 按分数从高到低排序 highscoreList.Sort((a, b) => b.score.CompareTo(a.score)); // 如果超过最大条数,移除最后一条(分数最低的) if (highscoreList.Count > MAX_HIGHSCORE_ENTRIES) { highscoreList.RemoveAt(highscoreList.Count - 1); } // 把排序后的记录存回Preferences SaveHighscoreList(highscoreList); } // 获取所有已存的高分记录 public List<(string name, int score)> GetAllHighscores() { List<(string name, int score)> result = new List<(string, int)>(); int entryCount = PlayerPrefs.GetInt(HIGHSCORE_COUNT_KEY, 0); for (int i = 0; i < entryCount; i++) { string nameKey = $"highscore_{i}_name"; string scoreKey = $"highscore_{i}_score"; string username = PlayerPrefs.GetString(nameKey, ""); int score = PlayerPrefs.GetInt(scoreKey, 0); // 跳过空用户名的无效记录 if (!string.IsNullOrEmpty(username)) { result.Add((username, score)); } } return result; } // 将整理好的高分列表存入Preferences private void SaveHighscoreList(List<(string name, int score)> highscoreList) { // 先清空旧的记录,避免残留数据 int oldEntryCount = PlayerPrefs.GetInt(HIGHSCORE_COUNT_KEY, 0); for (int i = 0; i < oldEntryCount; i++) { PlayerPrefs.DeleteKey($"highscore_{i}_name"); PlayerPrefs.DeleteKey($"highscore_{i}_score"); } // 写入新的记录 for (int i = 0; i < highscoreList.Count; i++) { PlayerPrefs.SetString($"highscore_{i}_name", highscoreList[i].name); PlayerPrefs.SetInt($"highscore_{i}_score", highscoreList[i].score); } // 更新总条数并保存到磁盘 PlayerPrefs.SetInt(HIGHSCORE_COUNT_KEY, highscoreList.Count); PlayerPrefs.Save(); } }
3. 在游戏结束界面显示排行榜
接下来在你的游戏结束UI脚本里,调用上面的方法获取数据并显示出来:
using UnityEngine; using TMPro; // 假设用TextMeshPro显示文本 public class GameEndPanel : MonoBehaviour { public HighscoreManager highscoreManager; public TMP_Text leaderboardDisplayText; void Start() { // 界面加载时就显示排行榜 RefreshLeaderboardDisplay(); } // 更新排行榜显示内容 public void RefreshLeaderboardDisplay() { var highscores = highscoreManager.GetAllHighscores(); string displayContent = "🏆 高分排行榜 🏆\n\n"; for (int i = 0; i < highscores.Count; i++) { displayContent += $"{i+1}. {highscores[i].name} - {highscores[i].score}分\n"; } // 如果没有记录,显示提示 if (highscores.Count == 0) { displayContent += "暂无记录,快来创造第一个高分吧!"; } leaderboardDisplayText.text = displayContent; } // 用户输入用户名并提交时调用 public void OnUsernameSubmitted(string username) { // 空用户名不提交 if (string.IsNullOrEmpty(username.Trim())) { return; } // 替换成你获取当前游戏得分的方法 int currentGameScore = GameManager.Instance.GetCurrentScore(); highscoreManager.AddNewHighscore(username.Trim(), currentGameScore); // 提交后刷新显示 RefreshLeaderboardDisplay(); } }
几个需要注意的细节
- 如果你之前存过单一的最高分键(比如
highscore),记得先调用PlayerPrefs.DeleteKey("highscore")清理掉,避免数据冲突 - 可以给用户名输入加个长度限制,比如最多10个字符,避免显示溢出
- 如果是其他引擎(比如Godot),把
PlayerPrefs换成对应引擎的Preferences API即可,核心逻辑完全一致
内容的提问来源于stack exchange,提问作者yetx95
相关产品推荐
相关产品推荐

