Can't get variable value outside task scope Firebase unity - c#

I'm here getting started with Firebase inside Unity. I figured out how to get data from my database. But the problem is that I can't get the value outside of the task that I am creating to get the data.
Here is the function that I am using, so you guys know what I am talking about:
public double GetBankBalance()
{
double bankBalance = 0;
Router.PlayerMoney("ymO6Hyl8WjbuPGaWV7FksbVABGb2").GetValueAsync().ContinueWith(task =>
{
if (task.IsFaulted)
{
Debug.Log("Error in GetBankBalance()");
}
else if (task.IsCompleted)
{
DataSnapshot snapshot = task.Result;
bankBalance = Convert.ToDouble(snapshot.Child("bankBalance").Value);
}
Debug.Log(bankBalance);
SetBankBalance(bankBalance);
});
Debug.Log(bankBalance);
return bankBalance;
}
I'll explain it a bit:
The "Router.PlayerMoney is just the path to the values that I need. The problem here is that inside the task the Debug.Log(bankBalance) returns the correct value but just outside (the Debug.Log above my return) the value is 0 as I gave bankBalance the value at the beginning of the function.
I can't seem to figure out what the problem is. I tried instance variables but that won't work.
Does anyone have an idea what might be the problem?

Related

how to reuse variable from function

I have the following code:
static int rnd_nmb()
{
Random rnda = new Random();
int skw1 = rnda.Next(1, 11);
return skw1;
}
private void function1()
{
rnd_nmb1();
MessageBox.Show(Convert.ToString(skw1));
}
I want to reuse the variable skw1 to show it on a Message Box, but it says:
"the name 'skw1' does not exist in the current context.".
I don't know what the problem is. Btw. it's a Windows Forms App and i'm using Visual Studio 2019.
I added the 'return' statement and thought it would work, but it doesn't.
there is no need to reuse the local variable, since you wrote a method named rnd_nmb which returns your desired value. Catch the returned value and use it:
private void function1()
{
int returnValue = rnd_nmb();
MessageBox.Show(returnValue.ToString);
}
I don't know what the problem is
One problem is the scope. The variable skw1 exists only withing the scope of the method in which it is declared. The scope is limited by { and }
Second problem is that you need to use the correct names when you try to call a method. You declared rnd_nmb but then you try to use rnd_nmb1
Third hint is that methods with a return value are exactly designed for the user to not care what happens inside of them. You use them and catch the result. It is like a toaster, you put bread in it and you catch the toasted stuff that come out in the end. You don't try to pull out the heating coil and use it on the bread, .... hopefully not... ;)

How do I read and write to the local storage in Blazor server side using Blazored?

Working on a Blazor server side project. I am using Blazored Local Storage for this: https://github.com/Blazored/LocalStorage
I have a dropdown, when a value is selected I want to store the value in local storage so that when the user returns to the page later the dropdown will be at the same value.
To accomplish this I bound the dropdown to the value _store and added a getter and setter. This part works:
private int _store {
get { return GetStoreValue(); }
set { SetStoreValue(value); }
}
Where it falls apart is the two functions for getting and setting:
private int GetStoreValue()
{
var returnValue = 0;
string storedValue = _storage.GetItemAsync<string>("UserListSelectedStore").ToString();
if (!string.IsNullOrEmpty(storedValue))
{
int storedValueInt = Int32.Parse(storedValue);
if (storedValueInt > 0)
{
returnValue = storedValueInt;
}
else
{
returnValue = _storeValue;
}
}
else
{
returnValue = _storeValue;
}
return returnValue;
}
private void SetStoreValue(int value)
{
_storage.SetItemAsStringAsync("UserListSelectedStore", value.ToString());
_storeValue = value;
}
Essentially, if there is a stored store value, use that. Otherwise return whatever was set when the component was initialized.
The problem - The value of storedValue is always an empty string "". It appears to write the value to storage correctly, but has problems reading it. Since this is a server side project, I have to use async for reading, I am not sure if that is the issue but I tried blindly changing it a few times and couldn't get it to work.
How do I get Blazor to read the stored value and return it if it exists?
Figured it out. I needed to add it to the OnInitializedAsync() method so everything gets set before the DOM loads.

Why does my app crash when a button is clicked?

I am trying to make a friends function into my Unity game. Each friend will have their own line with their name and a few buttons (challenge, about, etc.).
I have a friend row prefab and I instantiate it into the parent list for each friend.
It works just fine, until I click the challenge button, which whould call a method that takes in two parameters: the UId of the friend, and their username (two strings).
I am using Firebase Realtime Database for database.
void RetrieveFriendList(object sender, ValueChangedEventArgs args) {
foreach(Transform childTransform in listParent.GetComponentInChildren<Transform>()) {
GameObject.Destroy(childTransform.gameObject);
}
friends.Clear();
foreach (DataSnapshot s in args.Snapshot.Children) {
friends.Add(s.Key);
GameObject newRow = Instantiate(friendRowPrefab);
newRow.transform.Find("Deny").gameObject.GetComponent<Button>().onClick.RemoveAllListeners();
newRow.transform.Find("Challenge").gameObject.GetComponent<Button>().onClick.RemoveAllListeners();
newRow.transform.SetParent(listParent.transform);
newRow.transform.localScale = new Vector3(1f, 1f, 1f);
newRow.transform.Find("Text_Name").gameObject.GetComponent<TMPro.TMP_Text>().text = s.Child("username").Value.ToString();
string retrievedStatus = s.Child("type").Value.ToString();
if (retrievedStatus == "sent") {
newRow.transform.Find("Status").gameObject.GetComponent<TMPro.TMP_Text>().text = "Friend request sent";
} else if (retrievedStatus == "request") {
newRow.transform.Find("Status").gameObject.GetComponent<TMPro.TMP_Text>().text = "Incoming friend request";
newRow.transform.Find("Accept").gameObject.SetActive(true);
newRow.transform.Find("Deny").gameObject.SetActive(true);
newRow.transform.Find("Accept").gameObject.GetComponent<Button>().onClick.AddListener(delegate { AcceptFriendRequest(s.Key); });
newRow.transform.Find("Deny").gameObject.GetComponent<Button>().onClick.AddListener(delegate { DenyFriendRequest(s.Key); });
} else if (retrievedStatus == "friends") {
newRow.transform.Find("Challenge").gameObject.SetActive(true);
Debug.Log(s.Key + " - " + s.Child("username").Value.ToString());
newRow.transform.Find("Challenge").gameObject.GetComponent<Button>().onClick.AddListener(delegate { ChallengeFriend(s.Key, s.Child("username").Value.ToString()); }); //this is the line that causes the crash
newRow.transform.Find("About").gameObject.SetActive(true);
newRow.transform.Find("Status").gameObject.SetActive(false);
}
}
FirebaseDatabase.DefaultInstance.GetReference("users").Child(auth.CurrentUser.UserId).Child("friends").ValueChanged -= RetrieveFriendList;
}
What's likely happening is that the underlying C++ representation of your database snapshot is being cleaned up before your button accesses it. See this bug.
The easiest thing to do would be to find this line:
newRow.transform.Find("Challenge").gameObject.GetComponent<Button>().onClick.AddListener(delegate { ChallengeFriend(s.Key, s.Child("username").Value.ToString()); }); //this is the line that causes the crash
and turn it into something like:
var challengeKey = s.Key;
var challengeUsername = s.Child("username").Value.ToString();
newRow.transform.Find("Challenge").gameObject.GetComponent<Button>().onClick.AddListener(delegate { ChallengeFriend(challengeKey, challengeUsername); });
This way you retrieve the values you need (key and username) at the time of the callback rather than in the context of the button click (at some arbitrary point in the future after this function has returned). If you still get a crash, you may have to .Clone or .CopyTo the data -- but I believe that once an object is retrieved from the underlying snapshot it should be a full on C# object obeying the expected C# GC rules.
You also may experience null reference exceptions if the snapshot hits a local cache first -- so make sure you have null checks around everything (generally a good practice whenever you're hitting the web).

How to resolve this error with Unity's AsyncGPUReadback?

I am trying to read back from the GPU a compute buffer inside of which there is an array of structs that I have defined and previously set.
var req = AsyncGPUReadback.Request(myBuffer);
if(req.hasError == false)
{
var readback = req.GetData<myStruct>();
print(readback);
}
When I put this in the code I get this error: InvalidOperationException: Cannot access the data as it is not available. The problem is that the data should be available because when I use the normal GetData method everything works just fine.
myBuffer.GetData(data);
Does anyone have an idea where I should be looking to get this error solved? Thanks!
------------------------Edit-------------------------------
I found a solution here https://github.com/keijiro/AsyncCaptureTest/blob/master/Assets/AsyncCapture.cs , but It's not very clear to me why it is working now and not before.
void Update()
{
AsyncGPUReadback.Request(myBuffer, OnCompleteReadBack);
}
void OnCompleteReadBack(AsyncGPUReadBackRequest request)
{
if(request.hasError == false)
{
var data = request.GetData<myStruct>();
}
}

How to download data from Firebase?

I'm attempting to retrieve some data from a Firebase database. I've been able to do it fine in the past, but there's something wrong with my GetValueAsync() code below. When debugging it gets stuck at the "await reference.Database" line, but I'm not sure what I'm doing wrong. When running without debugging, none of the information is ever retrieved.
I'm uncertain if the problem is with the path, or the await/async function. Debugging shows that loggedUserId is storing the value before referencing it in the next line, but the rest of the function never completes or faults. The application compiles but I'm never able to capture any info from the snapshot.
The format of my database is "users" -> 78cVqzA8qNTNigsao3VvdnM0Qol2 (Which is correct) -> (several data pairs such as level : 1, lives : 3, etc)
public static async void GetUserData()
{
FirebaseApp app = FirebaseApp.DefaultInstance;
app.SetEditorDatabaseUrl("https://narwhaltrivia.firebaseio.com/");
if (app.Options.DatabaseUrl != null) app.SetEditorDatabaseUrl(app.Options.DatabaseUrl);
DatabaseReference reference = Firebase.Database.FirebaseDatabase.DefaultInstance.RootReference;
loggedUserId = FirebaseAuth.DefaultInstance.CurrentUser.UserId;
await reference.Database.GetReference("users").Child(loggedUserId).GetValueAsync().ContinueWith(task =>
{
if (task.IsFaulted)
{
Debug.LogError("Error retrieving user data");
return;
}
if (task.IsCompleted)
{
DataSnapshot userSnapshot = task.Result;
loggedEmail = userSnapshot.Child("email").GetRawJsonValue();
loggedCurrentScore = userSnapshot.Child("currentScore").GetRawJsonValue();
loggedLevel = userSnapshot.Child("level").GetRawJsonValue();
loggedLives = userSnapshot.Child("lives").GetRawJsonValue();
loggedRound = userSnapshot.Child("round").GetRawJsonValue();
loggedTotalScore = userSnapshot.Child("totalScore").GetRawJsonValue();
return;
}
});
}

Categories