Получение возвращаемого значения сопрограммы в единстве - PullRequest
0 голосов
/ 01 марта 2020

Я пытаюсь вставить пользователя во внешнюю базу данных в единстве. Мне нужно подождать, пока веб-сервер ответит с ошибкой или успехом, но я не могу это сделать ...

Вот что я сделал до сих пор:

public class DBConnector : MonoBehaviour
{
    string BASE_URL = "https://www.XXXXXX.com/API/";

    public DBConnector()
    {
    }

    public int registerUser(User user)
    {
        int returnInt = -1;

        StartCoroutine(RegisterUser(user, returnValue =>
        {
            returnInt = returnValue;
        }
        ));

        Debug.Log(returnInt);
        return returnInt;
    }

    IEnumerator RegisterUser(User user, System.Action<int> callback = null)
    {
        Debug.Log("a register user");

        WWWForm form = new WWWForm();

        using (UnityWebRequest www = UnityWebRequest.Post(BASE_URL + "userAPI.php", form))
        {
            yield return www.SendWebRequest();

            if (www.isNetworkError || www.isHttpError)
            {
                Debug.Log(www.error);
                yield return 1;
            }
            else
            {
                Debug.Log(www.downloadHandler.text);

                yield return 0;
            }
        }
    }
}

и вызывая его:

        Debug.Log("Before registerUser");

        conn = FindObjectOfType<DBConnector>();
        result = conn.registerUser(user);

        Debug.Log("After registerUser");

        if (result == 0)
        {
            SceneManager.LoadScene("AccountCreatedScene");
        }

обратный вызов RegisterUser завершается после того, как метод registerUser завершен sh, поэтому всегда возвращает -1.

Я совершенно новичок ie по работе в сети так что помогите пожалуйста ..... Как это сделать?

Спасибо

Ответы [ 2 ]

1 голос
/ 02 марта 2020

Также существует проблема:

    int returnInt = -1;

    //This is working async so it won't lock your method, just start your Coroutine and go
    StartCoroutine(RegisterUser(user, returnValue =>
    {
        //Inside callback
        returnInt = returnValue;
    }
    ));

    //go over there where your returnInt is always -1; you should insert that log inside callback
    Debug.Log(returnInt);

Короче говоря, вы должны реализовать остальную часть кода внутри этой лямбды

returnValue => {/ Здесь / };

, иначе он будет вызван до того, как ваша сопрограмма завершится

Я бы сделал это так:

public void RegisterUser(User user, System.Action<int> callback)
{
    StartCoroutine(RegisterUserCoroutine(user, callback);
}

IEnumerator RegisterUserCoroutine(User user, System.Action<int> callback = null)
{
    Debug.Log("a register user");

    WWWForm form = new WWWForm();

    using (UnityWebRequest www = UnityWebRequest.Post(BASE_URL + "userAPI.php", form))
    {
        yield return www.SendWebRequest();

        if (www.isNetworkError || www.isHttpError)
        {
            //This is also bad, because default value of your callback is null, so it would throw an error
            callback(1);

            //This is better
            callback?.Invoke(1);
        }
        else
        {
            callback(0);
        }
    }
}

Вы не можете получить это int в качестве возвращаемого значения , потому что вы используете асин c функцию. Таким образом, чтобы использовать этот код вместо:

int userId = RegisterUser( user );
DoSomethingWithUserId( userId );

, вы должны написать:

RegisterUser( user, DoSomethingWithUserId );
1 голос
/ 01 марта 2020

На самом деле вам нужно вызвать callback с возвращаемым значением, поэтому отправляемый вами делегат не вызывается.

IEnumerator RegisterUser(User user, System.Action<int> callback = null)
    {
        Debug.Log("a register user");

        WWWForm form = new WWWForm();

        using (UnityWebRequest www = UnityWebRequest.Post(BASE_URL + "userAPI.php", form))
        {
            yield return www.SendWebRequest();

            if (www.isNetworkError || www.isHttpError)
            {
                Debug.Log(www.error);
                if (callback != null) { callback.Invoke(1); }
            }
            else
            {
                Debug.Log(www.downloadHandler.text);

                if (callback != null) { callback.Invoke(0); }
            }
        }
    }

И вам нужно загрузить сцену внутри делегата, которого вы Отправить в; таким образом он будет вызван после того, как это будет сделано.

 public void Register(User user)
    {
        StartCoroutine(RegisterUser(user, returnValue =>
        {
            if (returnValue != 0) { 
              Debug.LogError("Error"); 
              return;
            }

            // Place any logic you want post login
            SceneManager.LoadScene("AccountCreatedScene");
        }
        ));
    }

РЕДАКТИРОВАТЬ: обратите внимание, что это псевдокод, который я написал в браузере.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...