You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity应用退出时如何等待协程执行完成后再退出并完成Web服务器数据保存

问题原因

Unity的OnApplicationQuit是同步执行的,函数执行完成后Unity会立即开始销毁所有场景对象、终止所有运行逻辑,不会等待协程yield return之后的异步逻辑执行,所以你的网络请求还没完成程序就已经退出了。

解决方案

通过Application.wantsToQuit事件拦截系统默认的退出流程,先执行保存数据的协程,等协程执行完成后再主动调用Application.Quit()退出应用。

具体修改步骤

  1. 新增退出拦截逻辑,替换原来的OnApplicationQuit方法
    在你项目中的全局管理类(比如GameManager)中添加如下代码:
private bool isProcessingQuit = false;

[RuntimeInitializeOnLoadMethod]
private static void RegisterQuitHandler()
{
    Application.wantsToQuit += OnTryQuitApplication;
}

private static bool OnTryQuitApplication()
{
    // 已经在执行退出前的保存流程,允许本次退出
    if (Instance.isProcessingQuit) return true;

    // 阻止默认退出流程,启动保存协程
    Instance.StartCoroutine(Instance.SaveDataThenQuit());
    return false;
}

private IEnumerator SaveDataThenQuit()
{
    isProcessingQuit = true;
    // 等待保存协程执行完成,最多等待5秒避免程序卡住无法退出
    float waitTimeout = 5f;
    bool saveDone = false;

    StartCoroutine(SaveGameDataAsync(GameManager.Instance.GetSaveData(), () => saveDone = true));

    yield return new WaitUntil(() =>
    {
        waitTimeout -= Time.unscaledDeltaTime;
        return saveDone || waitTimeout <= 0;
    });

    // 保存完成后主动调用退出
    Application.Quit();
}
  1. 改造原来的同步保存方法为可等待的协程
    把原来返回void的SaveGameData改成返回IEnumerator的异步版本,支持等待执行完成:
private IEnumerator SaveGameDataAsync(SaveData saveData, Action onFinish)
{
    try
    {
        string jsonString = JsonConvert.SerializeObject(saveData);
        // 等待用户数据上传协程执行完成
        yield return UserController.Instance.SaveGameLogInfo02Async("name", jsonString, timer);
    }
    catch (Exception e)
    {
        Debug.LogError($"保存数据失败: {e.Message}");
    }
    finally
    {
        onFinish?.Invoke();
    }
}
  1. 修改UserController中的保存方法,支持外部等待
// 新增异步可等待版本的保存方法
public IEnumerator SaveGameLogInfo02Async(string name, string rawdata, long time)
{
    if (saveGameLogInfoCoroutine02 == null)
    {
        saveGameLogInfoCoroutine02 = SaveGameLogInfoCoroutine02(name, rawdata, time);
        yield return StartCoroutine(saveGameLogInfoCoroutine02);
    }
    // 如果已经有正在执行的保存协程,等待它执行完成
    else
    {
        yield return new WaitUntil(() => saveGameLogInfoCoroutine02 == null);
    }
}

注意事项

  • 不要在OnApplicationQuit中执行任何异步、协程逻辑,该函数执行完成后所有对象都会被销毁,后续逻辑不会被执行
  • 超时机制是必要的,避免网络请求失败时程序卡住无法关闭
  • 该方案兼容PC、移动端平台,WebGL平台不存在本地退出逻辑不需要适配

内容的提问来源于stack exchange,提问作者doqltl179

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 14:36:03