Question: I'm trying to create a Class to manage my Cloud Firestore requests (like any SQLiteHelper Class). However, firebase uses async calls and I'm not able to return a value to other scripts.
Here an example (bool return):

```
    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));
            }
        });
    }

```

Answer: 
Unfortunately, since Firestore is acting as a frontend for some slow running I/O (disk access or a web request), any interactions you have with it will need to be asynchronous. You'll also want to avoid blocking your game loop if at all possible while performing this access. That is to say, there won't be a synchronous call to `GetSnapshotAsync`.

Now there are two options you have for writing code that *feels* synchronous (if you're like me, it's easier to think like this than with callbacks or reactive structures).

First is that `GetSnapshotAsync` returns a task. You can opt to `await` on that task in an `async` function:

```
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;
}

```

The catch with this is that `async`/`await` makes some assumptions about C# object lifecycle that aren't guaranteed in the Unity context (more information in my related [blog post](https://firebase.googleblog.com/2019/07/firebase-and-tasks-how-to-deal-with.html) and [video](https://www.youtube.com/watch?v=5GzFDXvZxKM)). If you're a long-time Unity developer, or just want to avoid `this == null` ever being true, you may opt to wrap your async call in a `WaitUntil` block:

```
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;
}

```

One other pattern I like to employ is [to use listeners](https://firebase.google.com/docs/firestore/query-data/listen#unity) instead of just retrieving a snapshot. I would populate some Unity-side class with whatever the latest data is from Firestore (or RTDB) and have all my Unity objects ping that MonoBehaviour. This fits especially well with [Unity's new ECS architecture](https://docs.unity3d.com/Packages/com.unity.entities@0.11/manual/index.html) or any time you're querying your data on a per-frame basis.

I hope that all helps!
This is how i got it to work, but excuse my ignorance as i've only been using FBDB for like a week.

Here is a snippet, I hope it helps someone.

Create a thread task extension to our login event

```
    static Task DI = new System.Threading.Tasks.Task(LoginAnon);

```

Logging in anon

```
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;
    });

```

And then get values.

```
            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;
                    }
                }
            });
        });

```

Obviously you can alter it how you like, It does not really need loops but i'm using them to test before i compact the code into something less readable and more intuitive.