Unity调用Golang生成的Agora令牌时遇重复发送请求错误
Unity请求Agora令牌报错:UnityWebRequest已发送无法重复发送
场景还原
用Golang搭建本地服务生成Agora令牌,Chrome访问http://localhost:8080/rte/agora/publisher/uid/1234/能正常获取RTC和RTM令牌,但在Unity中调用接口时触发错误。
相关代码
令牌请求工具类
public static class HelperClass { public static IEnumerator FetchToken(string url, string channel, int userId, Action<string> callback = null) { Debug.Log("Hitting Web Request"); UnityWebRequest request = UnityWebRequest.Get(string.Format("{0}/rtc/{1}/publisher/uid/{2}/", url, channel, userId)); yield return request.SendWebRequest(); if (request.isNetworkError || request.isHttpError) { Debug.Log("request"+request.error); callback(null); yield break; } TokenObject tokenInfo = JsonUtility.FromJson<TokenObject>(request.downloadHandler.text); callback(tokenInfo.rtcToken); } }
请求基础URL
internal static string _tokenBase = "http://localhost:8080/rte/agora/publisher/uid/";
调用方式
StartCoroutine(HelperClass.FetchToken(_tokenBase, _channelName, 0, this.RenewOrJoinToken));
报错信息
InvalidOperationException: UnityWebRequest has already been sent; cannot begin sending the request again UnityEngine.Networking.UnityWebRequest.SendWebRequest () (at /Users/bokken/buildslave/unity/build/Modules/UnityWebRequest/Public/UnityWebRequest.bindings.cs:266) Agora.Util.HelperClass+<FetchToken>d__0.MoveNext () (at Assets/Agora-RTC-Plugin/API-Example/Tools/RequestToken.cs:27) UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at /Users/bokken/buildslave/unity/build/Runtime/Export/Scripting/Coroutines.cs:17)
问题原因
错误核心是同一个UnityWebRequest实例被多次调用SendWebRequest(),通常由以下两种情况导致:
FetchToken协程被重复启动,同一个协程实例被多次执行,导致内部的request被重复发送- 回调方法
RenewOrJoinToken中再次触发了FetchToken调用,形成循环调用链
解决方案
1. 确保每次请求自动释放资源
使用using包裹UnityWebRequest,请求完成后自动释放资源,避免实例残留:
public static class HelperClass { public static IEnumerator FetchToken(string url, string channel, int userId, Action<string> callback = null) { Debug.Log("Hitting Web Request"); // using自动释放request资源 using (UnityWebRequest request = UnityWebRequest.Get(string.Format("{0}/rtc/{1}/publisher/uid/{2}/", url, channel, userId))) { yield return request.SendWebRequest(); if (request.isNetworkError || request.isHttpError) { Debug.Log("request"+request.error); callback?.Invoke(null); yield break; } TokenObject tokenInfo = JsonUtility.FromJson<TokenObject>(request.downloadHandler.text); callback?.Invoke(tokenInfo.rtcToken); } } }
2. 避免协程重复启动
保存协程引用,启动新协程前先停止旧的,防止重复执行:
// 在调用协程的类中声明变量保存协程引用 private Coroutine _tokenFetchCoroutine; // 调用时先停止旧协程 if (_tokenFetchCoroutine != null) { StopCoroutine(_tokenFetchCoroutine); } _tokenFetchCoroutine = StartCoroutine(HelperClass.FetchToken(_tokenBase, _channelName, 0, this.RenewOrJoinToken));
3. 检查回调逻辑
排查RenewOrJoinToken方法,确保没有在回调中再次调用FetchToken,避免循环触发请求。
内容的提问来源于stack exchange,提问作者Ziva
相关产品推荐
相关产品推荐

