Getting return value of a Coroutine in unity
本问题已经有最佳答案,请猛点这里访问。
我正在尝试将用户统一插入外部数据库。
我需要等到Web服务器回复错误或成功,但是我无法执行此操作。....
这是我到目前为止所做的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | 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; } } } } |
并调用它:
1 2 3 4 5 6 7 8 9 10 11 | Debug.Log("Before registerUser"); conn = FindObjectOfType<DBConnector>(); result = conn.registerUser(user); Debug.Log("After registerUser"); if (result == 0) { SceneManager.LoadScene("AccountCreatedScene"); } |
registerUser方法完成后,RegisterUser回调完成,因此始终返回-1。
我在联网方面还是个新手,所以请帮忙.....该怎么做?
谢谢
也有问题:
1 2 3 4 5 6 7 8 9 10 11 12 | 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); |
长话短说,您应该在lambda
内部实现其余代码
returnValue => {/此处/};
否则它将在协程完成之前被调用
我会这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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作为返回值,因为您使用的是异步函数。因此,使用该代码代替:
1 2 | int userId = RegisterUser( user ); DoSomethingWithUserId( userId ); |
您应该写:
1 | RegisterUser( user, DoSomethingWithUserId ); |
您实际上需要使用返回值调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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); } } } } |
您将需要将场景加载到您发送的委托中;这样,它将在完成后被调用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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"); } )); } |
编辑:请注意,这是我在浏览器中编写的伪代码。