![](/img/trans.png)
[英]Unity firestore - How to run GetSnapshotAsync() right after CheckAndFixDependenciesAsync()?
[英]Cloud Firestore GetSnapshotAsync to return a value. Unity and C#
我正在嘗試創建一個 Class 來管理我的 Cloud Firestore 請求(就像任何 SQLiteHelper 類一樣)。 但是,firebase 使用異步調用,我無法將值返回給其他腳本。 這里是一個例子(布爾返回):
public bool CheckIfIsFullyRegistered(string idUtente)
{
DocumentReference docRef = db.Collection("Utenti").Document(idUtente);
docRef.GetSnapshotAsync().ContinueWithOnMainThread(task =>
{
DocumentSnapshot snapshot = task.Result;
if (snapshot.Exists)
{
Debug.Log(String.Format("Document {0} exist!", snapshot.Id));
return true; //Error here
}
else
{
Debug.Log(String.Format("Document {0} does not exist!", snapshot.Id));
}
});
}
不幸的是,由於 Firestore 充當一些運行緩慢的 I/O(磁盤訪問或 web 請求)的前端,因此您與之進行的任何交互都需要是異步的。 在執行此訪問時,您還需要盡可能避免阻塞您的游戲循環。 也就是說,不會有對GetSnapshotAsync
的同步調用。
現在,您有兩種選擇可以編寫感覺同步的代碼(如果您像我一樣,這樣思考比使用回調或反應結構更容易)。
首先是GetSnapshotAsync
返回一個任務。 您可以選擇在async
function 中await
該任務:
public async bool CheckIfIsFullyRegistered(string idUtente)
{
DocumentReference docRef = db.Collection("Utenti").Document(idUtente);
// this is equivalent to `task.Result` in the continuation code
DocumentSnapshot snapshot = await docRef.GetSnapshotAsync()
return snapshot.Exists;
}
問題在於async
/ await
對 C# object 生命周期做出了一些假設,這些假設在 Unity 上下文中無法保證(更多信息在我的相關博客文章和視頻中)。 如果您是一名長期的 Unity 開發人員,或者只是想避免this == null
永遠為真,您可以選擇將異步調用包裝在WaitUntil
塊中:
private IEnumerator CheckIfIsFullyRegisteredInCoroutine() {
string idUtente;
// set idUtente somewhere here
var isFullyRegisteredTask = CheckIfIsFullyRegistered(idUtente);
yield return new WaitUntil(()=>isFullyRegisteredTask.IsComplete);
if (isFullyRegisteredTask.Exception != null) {
// do something with the exception here
yield break;
}
bool isFullyRegistered = isFullyRegisteredTask.Result;
}
我喜歡采用的另一種模式是使用偵聽器,而不僅僅是檢索快照。 我將使用來自 Firestore(或 RTDB)的任何最新數據填充一些 Unity 端 class,並讓我的所有 Unity 對象 ping MonoBehaviour。 這特別適合Unity 的新 ECS 架構或您在每幀基礎上查詢數據的任何時候。
希望對大家有幫助!
這就是我讓它工作的方式,但請原諒我的無知,因為我只使用了一周左右的 FBDB。
這是一個片段,我希望它對某人有所幫助。
為我們的登錄事件創建一個線程任務擴展
static Task DI = new System.Threading.Tasks.Task(LoginAnon);
匿名登錄
DI = FirebaseAuth.DefaultInstance.SignInAnonymouslyAsync().ContinueWith(result =>
{
Debug.Log("LOGIN [ID: " + result.Result.UserId + "]");
userID = result.Result.UserId;
FirebaseDatabase.DefaultInstance.GetReference("GlobalMsgs/").ChildAdded += HandleNewsAdded;
FirebaseDatabase.DefaultInstance.GetReference("Users/" + userID + "/infodata/nickname/").ValueChanged += HandleNameChanged;
FirebaseDatabase.DefaultInstance.GetReference("Users/" + userID + "/staticdata/status/").ValueChanged += HandleStatusChanged;
FirebaseDatabase.DefaultInstance.GetReference("Lobbies/").ChildAdded += HandleLobbyAdded;
FirebaseDatabase.DefaultInstance.GetReference("Lobbies/").ChildRemoved += HandleLobbyRemoved;
loggedIn = true;
});
然后獲取值。
DI.ContinueWith(Task =>
{
FirebaseDatabase.DefaultInstance.GetReference("Lobbies/" + selectedLobbyID + "/players/").GetValueAsync().ContinueWith((result) =>
{
DataSnapshot snap2 = result.Result;
Debug.Log("Their nickname is! -> " + snap2.Child("nickname").Value.ToString());
Debug.Log("Their uID is! -> " + snap2.Key.ToString());
//Add the user ID to the lobby list we have
foreach (List<string> lobbyData in onlineLobbies)
{
Debug.Log("Searching for lobby:" + lobbyData[0]);
if (selectedLobbyID == lobbyData[0].ToString()) //This is the id of the user hosting the lobby
{
Debug.Log("FOUND HOSTS LOBBY ->" + lobbyData[0]);
foreach (DataSnapshot snap3 in snap2.Children)
{
//add the user key to the lobby
lobbyData.Add(snap3.Key.ToString());
Debug.Log("Added " + snap3.Child("nickname").Value.ToString() + " with ID: " + snap3.Key.ToString() + " to local lobby.");
currentUsers++;
}
return;
}
}
});
});
顯然,您可以根據自己的喜好對其進行更改,它實際上並不需要循環,但我正在使用它們進行測試,然后再將代碼壓縮為可讀性較差且更直觀的內容。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.