簡體   English   中英

如果我啟用/禁用 Unity 游戲對象,為什么我的部分代碼沒有執行?

[英]Why is part of my code not executed if I enable/disable Unity gameObject?

我正在使用 PlayFab 並決定遷移到 Firebase。 我想使用 FirebaseAuth 在我的 Unity 游戲中實現登錄系統(並刪除了 PlayFab 代碼)。

所以我制作了一個 FirebaseManager.cs class,並修改了腳本執行順序,使其在任何其他自定義腳本之前運行。

我嘗試實現創建帳戶所需的內容,並且效果很好。 我知道 Firebase 默默地讓用戶在會話之間保持連接。 所以我想從我的“家庭場景”(這也是您登錄/創建帳戶的場景)檢查用戶是否已經連接。

public class FirebaseManager : MonoBehaviour
{
    private static FirebaseManager _instance;
    public static FirebaseManager Instance { ... }

    private FirebaseApp _app;

    private FirebaseAuth _auth;
    public FirebaseAuth Auth
    {
        get
        {
            if (_auth == null)
            {
                _auth = FirebaseAuth.GetAuth(_app);
            }
            return _auth;
        }
    }

    private FirebaseUser _user;
    public FirebaseUser User
    {
        get
        {
            return _user;
        }
        set
        {
            _user = value;
        }
    }

    // Events to subscribe to for this service
    public delegate void FirebaseInitialized();
    public static event FirebaseInitialized OnFirebaseInitialized;
    
    private void Awake()
    {
        if (_instance == null)
        {
            DontDestroyOnLoad(this.gameObject);
            _instance = this;
            InitializeFirebase();
        }
        else { Destroy(this.gameObject); }
    }

    private void InitializeFirebase()
    {
        Debug.Log($"FirebaseManager.cs > INITIALIZING FIREBASE");
        Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
        {
            var dependencyStatus = task.Result;
            if (dependencyStatus == Firebase.DependencyStatus.Available)
            {
                // Create and hold a reference to your FirebaseApp,
                // where app is a Firebase.FirebaseApp property of your application class.
                _app = FirebaseApp.DefaultInstance;

                // Create and hold a reference to FirebaseAuth
                _auth = FirebaseAuth.DefaultInstance;

                // Create and hold a reference to already logged in user (if any)
                _user = _auth.CurrentUser;

                if (OnFirebaseInitialized != null) OnFirebaseInitialized.Invoke();
            }
            else
            {
                UnityEngine.Debug.LogError(System.String.Format(
                  "Could not resolve all Firebase dependencies: {0}", dependencyStatus));
                // Firebase Unity SDK is not safe to use here.
            }
        });
    }

    private void OnDestroy()
    {
        if (_auth != null) _auth = null;
    }
}

我還做了一個 static AuthService.cs class 從我的場景中調用:

public static class AuthService
{
    private static FirebaseAuth auth = FirebaseManager.Instance.Auth;
    
    public static bool IsUserAlreadyLoggedIn()
    {
        Debug.Log($"AuthService.cs > Checking if user already logged in");
        return auth.CurrentUser != null;
    }
}

然后在我的登錄場景中,我有這個 LoginManager.cs class:

public class LoginManager : MonoBehaviour
{
    // Loading Animation
    [Header("Loading Animation")]
    public GameObject loadingAnimation;

    private void Awake()
    {
        FirebaseManager.OnFirebaseInitialized += OnFirebaseInitialized;
    }

    private void Start()
    {
        ShowLoadingAnimation(true);
    }

    private void OnFirebaseInitialized()
    {
        if (AuthService.IsUserAlreadyLoggedIn())
        {
            Debug.Log($"Already LoggedIn");
            OnLoginSuccess();
        }
        else
        {
            Debug.Log($"No User LoggedIn");
            ShowLoadingAnimation(false);
        }
    }

    private void OnLoginSuccess()
    {
        ShowLoadingAnimation(false); // From here, no code is executed
        Debug.Log($"Logged In as: {FirebaseManager.Instance.Auth.CurrentUser.Email}");
        // SceneLoader.Instance.Load(SceneLoader.Scene.CharacterCreation);
    }

    private void OnDestroy()
    {
        FirebaseManager.OnFirebaseInitialized -= OnFirebaseInitialized;
    }

    /// <summary>
    /// Show or Hide the Loading Animation
    /// </summary>
    /// <param name="show">True = show || False = hide</param>
    private void ShowLoadingAnimation(bool show)
    {
        loadingAnimation.SetActive(show);
    }
}

正在加載的 animation 游戲對象只是一個動畫圖像(+ 另一個用於阻止用戶輸入的圖像)。

每當代碼到達ShowLoadingAnimation()方法時。 之后的所有代碼都沒有執行。 但是,如果我刪除所有對ShowLoadingAnimation()的調用,一切正常。 同樣的邏輯在 PlayFab 上運行良好。

我只是不明白發生了什么。 也許與線程有關? 或者也許只是我的 Firebase 實現是錯誤的? 我能做些什么?

謝謝。

一種解釋是 OnFirebaseInitialized 在后台線程上被調用。

Unity 的 MonoBehaviour 系統不是線程安全的,因此如果從后台線程將 GameObject 設置為非活動狀態,這可能會導致異常和代碼執行停止。

為了避免這個問題,您可以讓 OnLoginSuccess 只需將 boolean 變量設置為 true,然后在 Update 方法(在主線程上調用)檢查此變量何時為 true 並調用 ShowLoadingAnimation(false)。

您還應該只在 lock 語句中訪問此 boolean 變量以確保線程安全。

所以我找到了解決方案。 正如 Sisus 所說(感謝您的回答,它在我的 Google 搜索中幫助了我),這個問題是由在另一個線程而不是主線程上運行的代碼引起的。

根據這個Firebase 視頻,在初始化 Firebase 時,我可以調用ContinueWithOnMainThread而不是簡單地ContinueWith來解決該問題。

(請注意,這需要using Firebase.Extensions ,請參閱Firebase.Extensions.TaskExtension 文檔

所以更新后的 Firebase 初始化看起來像這樣:

Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWithOnMainThread(task =>
{
    var dependencyStatus = task.Result;
    if (dependencyStatus == Firebase.DependencyStatus.Available)
    {
        // Create and hold a reference to your FirebaseApp,
        // where app is a Firebase.FirebaseApp property of your application class.
        _app = FirebaseApp.DefaultInstance;

        // Create and hold a reference to FirebaseAuth
        _auth = FirebaseAuth.DefaultInstance;

        // Create and hold a reference to already logged in user (if any)
        _user = _auth.CurrentUser;

        if (OnFirebaseInitialized != null) OnFirebaseInitialized.Invoke();
  }
  else
  {
      UnityEngine.Debug.LogError(System.String.Format(
      "Could not resolve all Firebase dependencies: {0}", dependencyStatus));
      // Firebase Unity SDK is not safe to use here.
  }

});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM