I searched how to wait coroutine in unity, and i found yield return StartCoroutine(IEnumerator). but when code start yield return, application quited. I want that application quit when every Coroutine finished. how can i fix this?
if can not wait Coroutine, how can i pause application quitting during data saved in web server.
private void OnApplicationQuit()
{
SaveGameData(GameManager.Instance.GetSaveData());
}
public void SaveGameData(SaveData saveData)
{
string jsonString = JsonConvert.SerializeObject(saveData);
UserController.Instance.SaveGameLogInfo02("name", jsonString, timer);
}
public void SaveGameLogInfo02(string name, string rawdata/*jsonArray형식*/, long time)
{
if(saveGameLogInfoCoroutine02 == null)
{
saveGameLogInfoCoroutine02 = SaveGameLogInfoCoroutine02(name, rawdata, time);
StartCoroutine(saveGameLogInfoCoroutine02);
}
}
private IEnumerator SaveGameLogInfoCoroutine02(string name, string rawdata/*jsonArray형식*/, long time)
{
yield return StartCoroutine(apiController.SaveGameLogInfo02(saveUserData.GetAccessToken(), name, rawdata, time));
SetJObject(apiController.RequestText);
if (GetResult())
{
Debug.Log(string.Format("Success saved {0}'s log data", name));
}
else
{
Debug.Log("code : " jo["code"] ", message : " jo["message"]);
}
saveGameLogInfoCoroutine02 = null;
yield break;
}
public IEnumerator SaveGameLogInfo02(string accessToken, string name, string rawdata, long time)
{
JObject json = new JObject();
json.Add("name", name);
json.Add("rawdata", rawdata);
json.Add("time", time);
yield return StartCoroutine(SendWebRequestWithTokenAndJson(accessToken, JsonConvert.SerializeObject(json), "/log/2/put"));
}
private IEnumerator SendWebRequestWithTokenAndJson(string token, string json, string path)
{
UnityWebRequest request = new UnityWebRequest(serverURL path, postMethod);
byte[] jsonToSend = new UTF8Encoding().GetBytes(json);
request.uploadHandler = new UploadHandlerRaw(jsonToSend);
request.downloadHandler = new DownloadHandlerBuffer();
request.SetRequestHeader("Authorization", "Bearer " token);
request.SetRequestHeader(requestName, requestValue);
yield return request.SendWebRequest();
RequestText = "";
if (request.result != UnityWebRequest.Result.Success)
{
Debug.LogError("Error While Sending: " request.error);
}
else
{
RequestText = request.downloadHandler.text;
}
yield break;
}
CodePudding user response:
You can't really. When the application quits your scene and everything is going to be unloaded -> No Coroutine will execute anymore
What you can try is using a blocking/synchronous call just for that case and do e.g.
private void SendWebRequestWithTokenAndJsonSynchronous(string token, string json, string path)
{
using(var request = new UnityWebRequest(serverURL path, postMethod))
{
var jsonToSend = new UTF8Encoding().GetBytes(json);
request.uploadHandler = new UploadHandlerRaw(jsonToSend);
request.downloadHandler = new DownloadHandlerBuffer();
request.SetRequestHeader("Authorization", "Bearer " token);
request.SetRequestHeader(requestName, requestValue);
request.SendWebRequest();
while(!request.isDone)
{
// Actually freeze until done
}
RequestText = "";
if (request.result != UnityWebRequest.Result.Success)
{
Debug.LogError("Error While Sending: " request.error);
}
Debug.Log("Upload successful!");
}
}
Or alternatively block the application from quitting using Application.wantsToQuit
but that's kind of tricky. (On iPhone this doesn't work! In the Editor this i also ignored!)
The idea here is:
- Every time you save store the time of the last save
- User wants to quit
- Check if the last save was "recently enough" so let's say e.g. within the last 30 seconds
- If yes, allow to quit
- If no upload a save now and then automatically quit
For this you would probably need to change your method signatures a bit and e.g. add a callback action you can pass into the routine and invoke it as soon as the upload finished.
Note that there is always still a chance that both doesn't work at all! Some devices (e.g. HoloLens) never really quits the app clean (except you explicitly built a button for it). There all applications are rather hibernated and the User can literally kill them kind of like via the TaskManager.
CodePudding user response:
Handle it with OnApplicationQuit()
public IEnumerator SaveGameLogInfo02(string accessToken, string name, string rawdata, long time)
{
JObject json = new JObject();
json.Add("name", name);
json.Add("rawdata", rawdata);
json.Add("time", time);
yield return StartCoroutine(SendWebRequestWithTokenAndJson(accessToken, JsonConvert.SerializeObject(json), "/log/2/put"));
allowQuitting = true;
Application.Quit();
}
void OnApplicationQuit()
{
// Delay quit
{
SaveGameData(GameManager.Instance.GetSaveData());
}
// Check permission to cancel if not done
if (!allowQuitting)
{
Application.CancelQuit();
}
}