You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity打包后Firebase RTDB事务报空引用异常无法正常工作

问题环境
  • 开发引擎:Unity 2020.3.22f1
  • 依赖版本:基于dotnet4的Firebase SDK 9.0.0,已同时导入Analytics、Real-Time Database(简称RTDB)两个功能模块
  • 功能现状:Analytics模块在所有运行场景下工作完全正常
  • 异常场景:三类正式发布包均触发RTDB相关报错:
    • 打包Android App Bundle上传至内部测试渠道
    • 打包APK直接安装到Android真机
    • 打包iOS版本上传至TestFlight
相关代码实现

Firebase初始化逻辑

FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task => {
    // 初始化Analytics
    FirebaseAnalytics.SetAnalyticsCollectionEnabled(true);

    DatabaseReference = FirebaseDatabase.DefaultInstance.RootReference;
    Debug.Log(JsonConvert.SerializeObject(DatabaseReference.Database.App.Options));
});

RTDB自增事务逻辑(关卡通关数统计)

DatabaseReference.Child("Levels").Child($"Level{levelNum}").Child("Wins").RunTransaction((mutableData) =>
{
    mutableData.Value = Int32.Parse(mutableData.Value.ToString()) + 1;
    return TransactionResult.Success(mutableData);
});
问题现象
  • Unity编辑器内运行无异常:初始化DatabaseReference后打印的Options配置可完整展示databaseUrl、apikey、AppId等所有属性
  • 真机/发布包运行异常:
    • Android真机调试APK时,打印的Options属性仅包含databaseUrl字段
    • 执行数据库事务操作时抛出如下空引用错误:
W/Unity: Exception in transaction delegate, aborting transaction
    System.NullReferenceException: Object reference not set to an instance of an object.
    at ....(Firebase.Database.MutableData mutableData)
已完成排查操作
  • 已配置调试密钥库、Google控制台应用完整性对应的SHA1/SHA256值
  • 已确认配置文件生成正常:streamingAssets文件夹、Assets\Plugins\Android\FirebaseApp.androidlib\res\values\google-services.xml路径下的XML配置均存在,且包含全部配置项
  • 已尝试手动初始化Firebase App:操作后Debug.Log可打印全部Options参数,但空引用报错仍存在;分别测试保留配置文件、完全删除配置文件两种场景,问题均未解决
  • 已尝试重写默认App实例的Options配置,问题未修复
  • 怀疑Proguard混淆可能引发Firebase相关错误,但未找到Unity平台对应的配置说明
解决思路

你遇到的空引用报错和配置、密钥、Proguard混淆都没有关系,核心问题是RTDB事务回调的写法不符合SDK的运行逻辑:
Firebase RTDB的RunTransaction触发后,第一次回调传入的mutableData.Value一定是null:SDK不会等拉取到服务端最新值才执行回调,会先传空值做一次本地预判,等拿到最新数据后才会第二次传入有效值进回调。你直接对null值调用ToString(),必然触发空引用异常。编辑器下不报错是因为本地存在之前连接的缓存值,跳过了首次空值回调的流程,真机首次启动无缓存就会必现报错。

直接修正事务逻辑,增加空值判断和类型兼容即可:

DatabaseReference.Child("Levels").Child($"Level{levelNum}").Child("Wins").RunTransaction((mutableData) =>
{
    // 首次空值回调直接返回,SDK拉取到最新数据后会再次触发回调
    if (mutableData.Value == null)
    {
        return TransactionResult.Success(mutableData);
    }
    
    int currentWins = 0;
    // Firebase存储数字类型默认返回long,直接强转int/Parse容易触发类型转换错误,做兼容处理
    if (mutableData.Value is long winsCount)
    {
        currentWins = (int)winsCount;
    }
    else
    {
        int.TryParse(mutableData.Value.ToString(), out currentWins);
    }

    mutableData.Value = currentWins + 1;
    return TransactionResult.Success(mutableData);
});

关于真机打印Options仅显示databaseUrl的现象,是Firebase Unity SDK在移动端的序列化逻辑做了内部字段裁剪,只要初始化流程不报错、数据库请求能正常发出,这个打印缺字段的现象不影响实际功能,不需要额外处理。

如果修正事务逻辑后仍存在连通问题,再补充Android端Proguard规则即可:在Player Settings中开启自定义Proguard配置文件,添加Firebase相关类的keep规则;iOS端不存在代码混淆问题,只要确保Firebase控制台下载的GoogleService-Info.plist放在项目Assets目录下即可。


内容的提问来源于stack exchange,提问作者Ben

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 20:42:17