- Home /
Callback with Action from one script to another only works partially
Hello everyone,
I am using callback functions for the first time and I have a behaviour which I cannot explain. I hope you can help me.
My aim is to get a return value (a warning text from a firebase connection) from within an IEnumerator from another script.
UIManager Skript:
public void RegisterButton()
{
string warningText = "";
StartCoroutine(FirebaseManager.instance.Register(emailRegisterField.text,
passwordRegisterField.text,
passwordRegisterVerifyField.text,
usernameRegisterField.text,
callbackWarningText =>
{
warningText = callbackWarningText;
Debug.Log("INSIDE: " + warningText);
}));
Debug.Log("OUTSIDE: " + warningText);
warningRegisterText.text = warningText;
}
FirebaseManager Skript:
public IEnumerator Register(string _email, string _password, string _confirmPassword, string _username, System.Action<string> callbackWarningText)
{
if (_username == "")
{
//If the username field is blank show a warning
callbackWarningText("Missing Username");
}
else if (_password != _confirmPassword)
{
//If the password does not match show a warning
callbackWarningText("Password Does Not Match!");
}
else
{
//Call the Firebase auth signin function passing the email and password
var RegisterTask = fbAuth.CreateUserWithEmailAndPasswordAsync(_email, _password);
//Wait until the task completes
yield return new WaitUntil(predicate: () => RegisterTask.IsCompleted);
if (RegisterTask.Exception != null)
{
//If there are errors handle them
Debug.LogWarning(message: $"Failed to register task with {RegisterTask.Exception}");
FirebaseException firebaseEx = RegisterTask.Exception.GetBaseException() as FirebaseException;
AuthError errorCode = (AuthError)firebaseEx.ErrorCode;
string message = "Register Failed!";
switch (errorCode)
{
case AuthError.MissingEmail:
message = "Missing Email";
break;
case AuthError.MissingPassword:
message = "Missing Password";
break;
case AuthError.WeakPassword:
message = "Weak Password";
break;
case AuthError.EmailAlreadyInUse:
message = "Email Already In Use";
break;
}
callbackWarningText(message);
...
I mentioned that it works partially in the title since the first 2 checks (username + password) in the firebaseManager work as expected. If one of them is true I get the following debug output:
INSIDE: Missing Username
OUTSIDE: Missing Username
However, if something from within the switch statement triggers, the debug output is:
OUTSIDE:
INSIDE: Missing Email
So, I do not get a return value in these cases.
What got my attention is that in the latter case the OUTSIDE string is logged first. This could mean that the code within RegisterButton() continues before the warningText is set within the FirebaseManager, but why and why only do I have different behaviours?
Answer by XoetziX · May 13, 2021 at 07:26 PM
Okay, I somehow solved the problem, but I would be really interested if anyone could explain me the difference!
I replaced the Lambda expression with a dedicated function (SetWarningText) and that's it, now the warning text is always filled and not only sometimes?!
public void RegisterButton()
{
StartCoroutine(FirebaseManager.instance.Register(emailRegisterField.text,
passwordRegisterField.text,
passwordRegisterVerifyField.text,
usernameRegisterField.text,
SetWarningText));
ClearRegisterFields();
ClearLoginFields();
}
private void SetWarningText(string returnValue)
{
string warningText = returnValue;
warningRegisterText.text = warningText;
}
Personal side note: Lambda expressions may be shorter, but they are much less easy to read. This is a good example in my opinion.
Sorry it's a little late but I'm thinking that:
Lambda expressions create anonymous methods that run in a way differently to normal methods. Instead of waiting for the method to finish before calling the next line of code like a normal method - anonymous methods can keep running when the method has returned/ended.
Therefore, it's not waiting for the database to be contacted - and may sometimes run before any text is returned. That's my guess. Glad you figured it out though. @XoetziX
Hello @Llama_w_2Ls Thanks for your reply, no it is not too late, since I still want to understand what happens here. :-)
I am wondering whether it has to do with the lambda expression or the coroutine. My thoughts: The actual problem occurs within line 13 (or 14) of the UIManager, since the OUTSIDE debug output is (sometimes) empty and before that the coroutine is started.
I have just recognized a point which may have to do with the problem: The WaitUntil in line 18 in my Firebase script.
Isn't it the purpose that the function waits for the return and that in the meantime the rest of the application continues? All CallbackWarningText calls before this line work find and the ones behind dont. That could be because the coroutine simply waits and the next command to be executed is the OUTSIDE debug statement.
Is this assumption of what happens in the background correct? Somehow it would be logical in my thoughts, however, this still does not explain why the problem does not occur anymore after switching from lambda to normal method?!?
Your answer
![](https://koobas.hobune.stream/wayback/20220613033708im_/https://answers.unity.com/themes/thub/images/avi.jpg)