Unity中从Firebase实时数据库拉取数据填充表格失败排查求助
Firebase Realtime Database数据拉取与Unity表格填充问题排查
问题说明
尝试从Firebase Realtime Database的timetable节点拉取数据,填充到Unity自制表格中,但运行场景时表格未被填充,需排查代码问题并确认节点引用正确性。
数据库结构

timetable节点下包含多个以数字命名的子节点,每个子节点包含fname、monday、tuesday、wednesday、thursday、friday字段。
原代码
using Firebase; using Firebase.Database; using System; using UnityEngine; using UnityEngine.UI; using Firebase.Unity; public class ScheduleRetriever : MonoBehaviour { // Table GameObject public GameObject table; // Prefab for table rows public GameObject rowPrefab; private DatabaseReference mDatabaseRef; private void Start() { // Initialize Firebase FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task => { var dependencyStatus = task.Result; if (dependencyStatus == Firebase.DependencyStatus.Available) { // Get reference to the "timetable" node mDatabaseRef = FirebaseDatabase.DefaultInstance.GetReference("timetable"); // Retrieve data from the "timetable" node mDatabaseRef.GetValueAsync().ContinueWith(task => { if (task.IsCompleted && !task.IsCanceled && !task.IsFaulted) { DataSnapshot snapshot = task.Result; // Iterate through the children of the snapshot foreach (var idChild in snapshot.Children) { DataSnapshot idSnapshot = idChild.Value as DataSnapshot; //DataSnapshot idSnapshot = idChild.Value as DataSnapshot; Debug.LogError("wut "); // Add the data to the table AddDataToTable(idChild); } } else { Debug.LogError("Data retrieval failed: " + task.Exception); } }); } else { Debug.LogError( "Could not resolve all Firebase dependencies: " + dependencyStatus); } }); } private void AddDataToTable(DataSnapshot idChild) { // Create a new row GameObject newRow = Instantiate(rowPrefab); // Set the parent of the new row to the table newRow.transform.SetParent(table.transform, false); // Get the text components of the new row Text[] rowTexts = newRow.GetComponentsInChildren<Text>(); // Set the text of the first column to the "fname" value retrieved from Firebase rowTexts[0].text = idChild.Child("fname").Value.ToString(); // Set the text of the second column to the "monday" value retrieved from Firebase rowTexts[1].text = idChild.Child("monday").Value.ToString(); // Set the text of the third column to the "tuesday" value retrieved from Firebase rowTexts[2].text = idChild.Child("tuesday").Value.ToString(); // Set the text of the fourth column to the "wednesday" value retrieved from Firebase rowTexts[3].text = idChild.Child("wednesday").Value.ToString(); // Set the text of the fifth column to the "thursday" value retrieved from Firebase rowTexts[4].text = idChild.Child("thursday").Value.ToString(); // Set the text of the sixth column to the "friday" value retrieved from Firebase rowTexts[5].text = idChild.Child("friday").Value.ToString(); } }
问题排查与修复
1. 节点引用确认
节点引用正确,FirebaseDatabase.DefaultInstance.GetReference("timetable")与数据库结构完全匹配。
2. 核心代码问题及修复
(1)后台线程操作UI
Firebase异步回调默认运行在后台线程,Unity UI操作必须在主线程执行,直接调用AddDataToTable会导致UI不更新。需替换ContinueWith为Firebase提供的ContinueWithOnMainThread,确保回调在主线程执行。
(2)无效类型转换
DataSnapshot idSnapshot = idChild.Value as DataSnapshot;是错误代码:idChild.Value返回的是数据值(如字典),而非DataSnapshot,且该行未被使用,直接删除即可。
(3)空值引用异常
若数据库中某个字段为null,调用.Value.ToString()会抛出异常,导致后续代码终止。需添加空值判断。
(4)调试日志不足
原日志仅输出无意义内容,需添加节点数量、子节点键值等日志,便于确认数据是否正确拉取。
修复后代码
using Firebase; using Firebase.Database; using UnityEngine; using UnityEngine.UI; using Firebase.Unity; public class ScheduleRetriever : MonoBehaviour { public GameObject table; public GameObject rowPrefab; private DatabaseReference mDatabaseRef; private void Start() { FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task => { var dependencyStatus = task.Result; if (dependencyStatus == Firebase.DependencyStatus.Available) { mDatabaseRef = FirebaseDatabase.DefaultInstance.GetReference("timetable"); mDatabaseRef.GetValueAsync().ContinueWithOnMainThread(task => { if (task.IsCompleted && !task.IsCanceled && !task.IsFaulted) { DataSnapshot snapshot = task.Result; Debug.Log($"拉取到{timetable}节点子节点数量:{snapshot.ChildrenCount}"); foreach (var idChild in snapshot.Children) { Debug.Log($"当前子节点键:{idChild.Key},数据:{idChild.Value}"); AddDataToTable(idChild); } } else { Debug.LogError("数据拉取失败:" + task.Exception?.Message); } }); } else { Debug.LogError("无法解析Firebase依赖:" + dependencyStatus); } }); } private void AddDataToTable(DataSnapshot idChild) { GameObject newRow = Instantiate(rowPrefab); newRow.transform.SetParent(table.transform, false); Text[] rowTexts = newRow.GetComponentsInChildren<Text>(); // 空值处理,避免空引用异常 rowTexts[0].text = idChild.Child("fname").Value?.ToString() ?? "无数据"; rowTexts[1].text = idChild.Child("monday").Value?.ToString() ?? "无数据"; rowTexts[2].text = idChild.Child("tuesday").Value?.ToString() ?? "无数据"; rowTexts[3].text = idChild.Child("wednesday").Value?.ToString() ?? "无数据"; rowTexts[4].text = idChild.Child("thursday").Value?.ToString() ?? "无数据"; rowTexts[5].text = idChild.Child("friday").Value?.ToString() ?? "无数据"; } }
额外检查项
- 确认
table和rowPrefab已在Inspector中正确赋值,且rowPrefab的子物体包含6个Text组件,顺序与代码索引对应。 - 检查Firebase数据库规则是否允许读取(测试阶段可临时设置为
{ "rules": { ".read": true, ".write": true } })。 - 查看Unity Console是否有权限、依赖相关报错。
内容的提问来源于stack exchange,提问作者alif
相关产品推荐
相关产品推荐

