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

Unity协程结合UnityWebRequest异常:未等Token赋值就执行后续逻辑

解决Unity协程未等待Web请求完成就执行后续逻辑的问题

你的问题核心在于Unity协程是异步执行的:调用StartCoroutine(GetToken(...))后,主线程不会暂停等待协程跑完,而是直接继续执行后面的Debug.Log和CreateOrJoinRoom,这时候m_Token还没被赋值,自然会出问题。

下面给两种实用的解决方法:

方法一:将后续逻辑移到协程的成功分支内

直接把需要依赖token的代码放在GetToken协程获取成功的分支里,确保只有拿到token后才执行后续操作:

修改后的ConnectToLiveKit方法:

public void ConnectToLiveKit(string Username, string RoomName){
    string query = $"?roomname={RoomName}&username={Username}";
    string fullUri = ServiceURL + query;
    // 把用户名和房间名传给协程,方便后续调用
    StartCoroutine(GetToken(fullUri, Username, RoomName));
}

修改后的GetToken协程:

IEnumerator GetToken(string uri, string username, string roomName)
{
    Debug.Log("Getting Token at " + uri + " ...");
    UnityWebRequest webRequest = UnityWebRequest.Get(uri);
    yield return webRequest.SendWebRequest();

    string[] pages = uri.Split('/');
    int page = pages.Length - 1;

    switch (webRequest.result)
    {
        case UnityWebRequest.Result.ConnectionError:
        case UnityWebRequest.Result.DataProcessingError:
            Debug.LogError(pages[page] + ": Error: " + webRequest.error);
            // 这里添加token获取失败的处理逻辑
            break;
        case UnityWebRequest.Result.ProtocolError:
            Debug.LogError(pages[page] + ": HTTP Error: " + webRequest.error);
            // 处理HTTP协议错误
            break;
        case UnityWebRequest.Result.Success:
            Debug.Log(pages[page] + ":\nReceived: " + webRequest.downloadHandler.text);
            m_Token = webRequest.downloadHandler.text;
            // 现在token已赋值,执行后续逻辑
            Debug.Log($"Token: {m_Token}");
            StartCoroutine(CreateOrJoinRoom(username, roomName));
            break;
    }
    // 手动释放WebRequest资源(原代码的using被注释了,必须手动处理)
    webRequest.Dispose();
}

方法二:使用回调委托(更灵活的场景)

如果你的GetToken需要在多个地方调用,且每个地方的后续逻辑不同,可以用回调委托来解耦:

首先定义回调类型:

// token获取成功的回调
private delegate void OnTokenReceived(string token);
// token获取失败的回调
private delegate void OnTokenFailed();

修改GetToken协程:

IEnumerator GetToken(string uri, OnTokenReceived onSuccess, OnTokenFailed onFailure)
{
    Debug.Log("Getting Token at " + uri + " ...");
    UnityWebRequest webRequest = UnityWebRequest.Get(uri);
    yield return webRequest.SendWebRequest();

    string[] pages = uri.Split('/');
    int page = pages.Length - 1;

    switch (webRequest.result)
    {
        case UnityWebRequest.Result.ConnectionError:
        case UnityWebRequest.Result.DataProcessingError:
        case UnityWebRequest.Result.ProtocolError:
            Debug.LogError(pages[page] + ": Error: " + webRequest.error);
            onFailure?.Invoke();
            break;
        case UnityWebRequest.Result.Success:
            string token = webRequest.downloadHandler.text;
            Debug.Log(pages[page] + ":\nReceived: " + token);
            m_Token = token;
            onSuccess?.Invoke(token);
            break;
    }
    webRequest.Dispose();
}

调用时传入自定义的后续逻辑:

public void ConnectToLiveKit(string Username, string RoomName){
    string query = $"?roomname={RoomName}&username={Username}";
    string fullUri = ServiceURL + query;
    
    StartCoroutine(GetToken(fullUri, 
        // 成功回调:拿到token后执行的逻辑
        (token) => {
            Debug.Log($"Token: {token}");
            StartCoroutine(CreateOrJoinRoom(Username, RoomName));
        }, 
        // 失败回调:获取token失败时的处理
        () => {
            Debug.LogError("Failed to retrieve token, cannot join room");
        }));
}

关键提醒

  • 一定要记得释放UnityWebRequest资源,不管是用using块还是手动调用Dispose(),否则会造成内存泄漏。
  • 协程的本质是状态机,yield return会暂停协程执行,直到等待的操作完成,主线程会继续处理其他任务,这是Unity异步编程的核心特点。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 08:02:10