Unity接入Firebase实现登录时ContinueWith内除Debug外功能不生效
问题根源
Firebase的异步方法(比如SignInWithEmailAndPasswordAsync)的ContinueWith回调默认运行在后台线程,而Unity规定所有UI修改、场景加载、Unity核心API调用都必须在主线程执行。Debug.Log是线程安全的所以可以正常输出,其他操作自然不会生效,部分情况还会触发静默报错。
解决方案
方案1:使用Firebase官方提供的ContinueWithOnMainThread(推荐)
Firebase Unity SDK专门封装了主线程调度的扩展方法,直接替换原来的ContinueWith即可,无需额外写工具类。
修改后代码如下:
public void Login() { string email = emailInputField.text; string password = passwordInputField.text; // 把ContinueWith替换为ContinueWithOnMainThread auth.SignInWithEmailAndPasswordAsync(email, password).ContinueWithOnMainThread( task => { if (task.IsCompleted && !task.IsCanceled && !task.IsFaulted) { Debug.Log("[Login Success] ID: " + auth.CurrentUser.UserId); PlayerInformation.auth = auth; SceneManager.LoadScene("SongSelectScene"); } else { messageUI.text = "[Login Failed] Please check your account"; Debug.Log("[Login Failed] Please check your account"); } }); }
方案2:自定义主线程调度器(适配旧版SDK)
如果你的Firebase SDK版本较低没有内置ContinueWithOnMainThread,可以自己实现一个主线程调度工具:
- 新建
MainThreadDispatcher单例类,挂载到常驻场景的物体上:
using System; using System.Collections.Generic; using UnityEngine; public class MainThreadDispatcher : MonoBehaviour { public static MainThreadDispatcher Instance; private readonly Queue<Action> _executionQueue = new Queue<Action>(); private void Awake() { if (Instance == null) { Instance = this; DontDestroyOnLoad(gameObject); } else { Destroy(gameObject); } } private void Update() { lock (_executionQueue) { while (_executionQueue.Count > 0) { _executionQueue.Dequeue().Invoke(); } } } public void Enqueue(Action action) { lock (_executionQueue) { _executionQueue.Enqueue(action); } } }
- 回调中将需要主线程执行的代码丢到调度器队列:
public void Login() { string email = emailInputField.text; string password = passwordInputField.text; auth.SignInWithEmailAndPasswordAsync(email, password).ContinueWith( task => { // 把所有Unity API操作放到主线程调度 MainThreadDispatcher.Instance.Enqueue(() => { if (task.IsCompleted && !task.IsCanceled && !task.IsFaulted) { Debug.Log("[Login Success] ID: " + auth.CurrentUser.UserId); PlayerInformation.auth = auth; SceneManager.LoadScene("SongSelectScene"); } else { messageUI.text = "[Login Failed] Please check your account"; Debug.Log("[Login Failed] Please check your account"); } }); }); }
额外注意事项
- 请提前确认
SongSelectScene已经添加到Unity的Build Settings > Scenes In Build列表中,否则场景加载也会失败 - 优先使用方案1,实现简单且不会有自定义调度器的潜在线程安全问题
内容的提问来源于stack exchange,提问作者tesSer-16
相关产品推荐
相关产品推荐

