如何按降序查询Firebase Score集合高分并在TextMeshPro展示
搞定Firebase分数排序展示到TextMeshPro的问题
先查最容易踩的坑
首先确认你Firebase里Score集合的分数字段(比如叫score)是纯数值类型,要是存成字符串,排序会按字典序来(比如"100"会排在"99"前面),这绝对是高频翻车点。
修复后的完整代码
假设你的分数字段叫score,下面是能正常跑的代码:
using UnityEngine; using TMPro; using Firebase.Firestore; using System.Collections.Generic; public class ScoreDisplay : MonoBehaviour { public TextMeshProUGUI scoreText; private FirebaseFirestore db; void Start() { db = FirebaseFirestore.DefaultInstance; FetchAndDisplayScores(); } void FetchAndDisplayScores() { // 构建查询:按score降序排,这里限制只取前10条高分,可按需调整 Query scoreQuery = db.Collection("Score") .OrderByDescending("score") .Limit(10); // 异步拿数据 scoreQuery.GetSnapshotAsync().ContinueWith(task => { if (task.IsFaulted) { Debug.LogError("拿分数失败: " + task.Exception); return; } QuerySnapshot snapshot = task.Result; string scoreDisplayText = "高分榜:\n"; // 遍历结果拼文本 foreach (DocumentSnapshot doc in snapshot.Documents) { Dictionary<string, object> scoreData = doc.ToDictionary(); // 先检查字段存不存在,而且得是数值类型 if (scoreData.ContainsKey("score") && scoreData["score"] is long scoreValue) { string playerName = scoreData.ContainsKey("playerName") ? scoreData["playerName"].ToString() : "匿名玩家"; scoreDisplayText += $"{playerName}: {scoreValue}\n"; } } // 必须切回主线程更UI!Firebase回调在子线程,直接改会崩 UnityMainThreadDispatcher.Instance().Enqueue(() => { scoreText.text = scoreDisplayText; }); }); } }
关键修复点
- 排序逻辑要对:用
OrderByDescending("score")才是从高到低排,注意字段名要和Firebase里的完全一致(大小写敏感!别写错)。 - 主线程更UI:Firebase的回调是在子线程跑的,直接改TextMeshPro会没反应甚至报错,必须用主线程调度器。如果你的项目里没有这个调度器,自己加个简单的:
using UnityEngine; using System.Collections.Generic; public class UnityMainThreadDispatcher : MonoBehaviour { private static UnityMainThreadDispatcher _instance; private Queue<System.Action> _actions = new Queue<System.Action>(); public static UnityMainThreadDispatcher Instance() { if (_instance == null) { _instance = FindObjectOfType<UnityMainThreadDispatcher>(); if (_instance == null) { GameObject obj = new GameObject("MainThreadDispatcher"); _instance = obj.AddComponent<UnityMainThreadDispatcher>(); DontDestroyOnLoad(obj); } } return _instance; } void Update() { lock (_actions) { while (_actions.Count > 0) { _actions.Dequeue().Invoke(); } } } public void Enqueue(System.Action action) { lock (_actions) { _actions.Enqueue(action); } } }
- 数据类型要对:从Firebase读出来的分数得是数值(long或int),要是之前存的是字符串,赶紧去Firebase控制台改成数值类型再测试。
额外要注意的
- 检查Firebase的安全规则,确保
Score集合能被读取,不然查询直接被拒:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /Score/{document} {
allow read, write: if true; // 测试用,上线记得改成正经权限控制
}
}
}
- 测试的时候可以在Firebase控制台手动加几条不同分数的数据,看看排序对不对。
内容的提问来源于stack exchange,提问作者Derpling
相关产品推荐
相关产品推荐

