简体   繁体   中英

UnityEngine.UI.Text is not updating inside async method

i have a script MenuManager.cs amd i this script i get tow doc in the firebase firestone, and this works well but when i will set the result in a text, dont work

using Firebase.Firestore;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization.Json;
using UnityEngine;

public class MenuManager : MonoBehaviour
{
    private Usuario usuario;
    private Rank rank;
    private CollectionReference usuarioCollection;
    private CollectionReference rankCollection;

    public GameObject rankNomeLabel;

    public bool infoCarregadas;

    public GameObject botaoInfo;
    
    void Start()
    {
        this.rank = new Rank();
        this.botaoInfo.GetComponent<UnityEngine.UI.Button>().onClick.AddListener(() => this.CarregaInfos());
        //this.infoCarregadas = false;
    }
    
    void Update()
    {
        /*if (db != null && infoCarregadas == false)
        {
            this.CarregaInfos();
        } else
        {
            if (infoCarregadas == false)
            {
                db = FirebaseAuthenticator.instance.fsDB;
            }
            
        }*/
    }

    private void CarregaInfos()
    {
        try
        {
            FirebaseFirestore db = FirebaseAuthenticator.instance.fsDB;
            var usuarioJson = PlayerPrefs.GetString("usuario");
            this.usuario = usuarioJson != "" ? JsonUtility.FromJson<Usuario>(usuarioJson) : null;
            if (this.usuario != null && this.usuario.UID != null)
            {
                this.usuarioCollection = db.Collection("usuario");
                DocumentReference docRef = this.usuarioCollection.Document(usuario.UID);
                docRef.GetSnapshotAsync().ContinueWith(task =>
                {
                    DocumentSnapshot snapshot = task.Result;
                    if (snapshot.Exists)
                    {
                        Dictionary<string, object> usuario = snapshot.ToDictionary();

                        foreach (KeyValuePair<string, object> pair in usuario)
                        {
                            if (pair.Key == "rank")
                            {
                                this.rankCollection = db.Collection("rank");
                                DocumentReference docRef = this.rankCollection.Document(pair.Value.ToString());
                                docRef.GetSnapshotAsync().ContinueWith(task =>
                                {
                                    DocumentSnapshot snapshot = task.Result;
                                    if (snapshot.Exists)
                                    {
                                        Dictionary<string, object> rank = snapshot.ToDictionary();

                                        foreach (KeyValuePair<string, object> pair in rank)
                                        {
                                            if (pair.Key == "nome")
                                            {
                                                this.rankNomeLabel.GetComponent<UnityEngine.UI.Text>().text = pair.Value.ToString();
                                            }
                                        }
                                    }
                                    else
                                    {
                                        Debug.Log("Erro ao carregar o rank: " + snapshot.Id);
                                    }
                                });
                            }
                        }
                    }
                    else
                    {
                        Debug.Log("Erro ao carregar o usuário: " + snapshot.Id);
                    }
                });
            }
            else
            {
                Debug.Log("Erro ao pegar usuário do PlayerPrefs");
            }
        }
        catch (Exception e)
        {
            Debug.LogError("Erro: " + e);
        }
    }
}

the text is linked to the variable (print bellow)

在此处输入图像描述 在此处输入图像描述

this.rankNomeLabel.GetComponent<UnityEngine.UI.Text>().text = pair.Value.ToString(); in this line, the reference is null

think the problem is in setting the value within the async method but I don't know how to fix it

does anyone know what's going on?

Most of the Unity API can only be used on the Unity main thread (the exception are pure structs since they are only data containers and don't immediately rely on or influence the actual scene).

ContinueWith is not guaranteed to be executed in the main thread.

Therefore Firebase provides the Extension method ContinueWithOnMainThread .

Replacing both or at least the inner ContinueWith by ContinueWithOnMainThreae should solve your issue or at least make it clearer where the actual issue is.


Instead of using GetComponent over and over again make your live easier and directly use the correct types

using UnityEngine.UI;

...

public Text rankNomeLabel;
public Button botaoInfo;

this also makes sure you can only drag in objects that actually have the according component attached and is less error prone on runtime since it makes already sure it isn't null - and if it is (eg if the object was destroyed) you can also see it immediately in the Inspector

I solved a similar issue by checking a boolean in an update method. It's not fancy but it works.

public class MyClass : MonoBehaviour
{
    private bool updateUI = false;

    private async Task function() {
        updateUI = true;
    }

    private void Update() {
        if (updateUI) {
            // update your ui here
            ...
            updateUI = false;
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM