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

Unity接入Firebase双管理类并行初始化出现竞态仅单实例生效

问题根因

你遇到的竞态问题核心来源是两个Manager类的Awake中同时调用了FirebaseApp.CheckAndFixDependenciesAsync():

  • Firebase的依赖检查与修复是全局独占操作,官方明确要求整个应用生命周期内仅能执行一次,并发调用会破坏FirebaseApp全局实例的内部状态
  • 其次ContinueWith默认返回的是后台工作线程,直接在后台线程调用Firebase Auth/Database的DefaultInstance属性也有概率触发线程安全问题导致空引用
解决方案

方案1:抽离全局统一初始化入口(推荐)

新增全局唯一的Firebase初始化单例,等依赖准备完成后再分别触发两个业务Manager的初始化逻辑,既避免并发调用依赖检查,也保持你原来的业务逻辑拆分的架构。

1. 新增FirebaseInitializer.cs

public class FirebaseInitializer : MonoBehaviour
{
    public static FirebaseInitializer instance;
    public DependencyStatus dependencyStatus;
    // 依赖准备完成的回调事件
    public event Action OnFirebaseDependenciesReady;

    void Awake()
    {
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
            // 全局仅执行一次依赖检查
            FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task =>
            {
                dependencyStatus = task.Result;
                if (dependencyStatus == DependencyStatus.Available)
                {
                    // 通知所有订阅的Manager执行初始化
                    OnFirebaseDependenciesReady?.Invoke();
                }
                else
                {
                    Debug.LogError("Firebase依赖修复失败: " + dependencyStatus);
                }
            });
        }
        else
        {
            Destroy(gameObject);
        }
    }
}

2. 修改FirebaseManagerAuth.cs

删除Awake中的依赖检查逻辑,改为订阅初始化事件:

public class FirebaseManagerAuth : MonoBehaviour
{
    public static FirebaseManagerAuth instance;
    [SerializeField] private PlayerDataSO playerData;

    [Header("Firebase")]
    public FirebaseAuth fbAuth;
    public FirebaseUser fbUser;

    void Awake()
    {
        if (instance == null)
        {
            instance = this;
            // 订阅依赖准备完成事件
            FirebaseInitializer.instance.OnFirebaseDependenciesReady += InitializeFirebase;
        }
        else
        {
            Destroy(gameObject);
        }
    }

    private void InitializeFirebase()
    {
        try
        {
            fbAuth = FirebaseAuth.DefaultInstance;
            Debug.Log("Firebase Auth初始化完成");
        }
        catch (Exception e)
        {
            Debug.LogError("AUTH初始化失败: " + e.Message);
        }
    }
}

3. 修改FirebaseManagerGame.cs

和Auth类逻辑一致,改为订阅初始化事件:

public class FirebaseManagerGame : MonoBehaviour
{
    public static FirebaseManagerGame instance;
    [SerializeField] private PlayerDataSO playerData;

    [Header("Firebase")]
    public DatabaseReference DBreference;

    void Awake()
    {
        if (instance == null)
        {
            instance = this;
            // 订阅依赖准备完成事件
            FirebaseInitializer.instance.OnFirebaseDependenciesReady += InitializeFirebase;
        }
        else
        {
            Destroy(gameObject);
        }
    }

    private void InitializeFirebase()
    {
        try
        {
            DBreference = FirebaseDatabase.DefaultInstance.RootReference;
            Debug.Log("Firebase Database初始化完成,引用: " + DBreference.ToString());
        }
        catch (Exception e)
        {
            Debug.LogError("GAME初始化失败: " + e.Message);
        }
    }
}

场景配置说明

把FirebaseInitializer挂载到场景中优先级最高的GameObject上,调整脚本执行顺序,保证FirebaseInitializer的Awake早于两个Manager的Awake执行即可。

方案2:加静态标记位避免重复调用依赖检查

如果不想新增类,也可以给两个Manager加静态的依赖检查标记:

// 新增静态全局标记
private static bool _isDependenciesChecked = false;
private static readonly object _lockObj = new object();

void Awake()
{
    // 单例逻辑保持不变
    if (instance == null)
    {
        instance = this;
        lock(_lockObj)
        {
            if (!_isDependenciesChecked)
            {
                _isDependenciesChecked = true;
                FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task =>
                {
                    // 初始化逻辑和原来一致
                });
            }
        }
    }
    else
    {
        Destroy(gameObject);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 17:06:08