在嵌套协程中挣扎着从 while 循环返回数据

Struggling with returning data from a while loop inside nested Coroutine

提问人:1nKy 提问时间:7/12/2023 更新时间:7/12/2023 访问量:37

问:

这是我在stackOverflow上发布的第一个问题!我正在尝试为 Unity 游戏开发 AssetBundle 更新程序。我用于确保一个操作在下一个操作开始之前完成。yield return StartCoroutine()

我正在尝试做的是显示下载的文件在 Textmesh 对象上下载时的百分比。

这是代码。 本身就是从另一个脚本启动的协程。DownloadCoroutineLauncher()

public IEnumerator DownloadCoroutineLauncher(){
        yield return StartCoroutine(InitialSetup());
        //Ensures that we have the correct local file structure.
        yield return StartCoroutine(EnsureFileStructureAndInitialVersionDoc());
        //Just tells us which files to get from remote.
        yield return StartCoroutine(EnsureCorrectPlatform());
        yield return StartCoroutine(FinalizeInitialSetup());
        //At this point we should at the very least have an initial version file.
        //Set up the local version dictionary.
        yield return StartCoroutine(LocalDictionarySetup());
        //Download the version file and set up the remote version dictionary.
        yield return StartCoroutine(DownloadVersionFile());
        //Figure out what new files need to be downloaded or overwritten.
        yield return StartCoroutine(FigureOutWhatToUpdate());
        //Determine files needing deletion.
        yield return StartCoroutine(FigureOutWhatToDelete());
        //Download what needs downloading.
        foreach(KeyValuePair<string,bool> file in whatToUpdate){
            if(file.Value == true){
                yield return StartCoroutine(DownloadAssetBundle(localFiles[file.Key],remoteFiles[file.Key],"Downloading " + file.Key));
            }
        }
        /*Delete what needs deleting. Future Feature.
        foreach(KeyValuePair<string,string> file in whatToDelete){

        }*/
        //Finally, update the local version doc
        yield return StartCoroutine(UpdateVersionDoc());
        yield return null;

    }

问题出在 DownloadAssetBundle 协程内部。

    IEnumerator DownloadAssetBundle(string localLocation, string remoteLocation, string niceText){
        yield return CurrentItemText.text = niceText; //This returns and updates the TMP text correctly.
        var cert = new ForceAcceptAll();
        UnityWebRequest request = new UnityWebRequest(remoteLocation,UnityWebRequest.kHttpVerbGET);
        request.certificateHandler = cert;
        request.downloadHandler = new DownloadHandlerFile(localLocation);
        yield return request.SendWebRequest();
        cert?.Dispose();
        while (!request.isDone){
            Debug.Log((request.downloadProgress * 100.0f).ToString() + "%"); //troubleshooting line. Also doesn't trigger.
            ProgressText.text = (request.downloadProgress * 100.0f).ToString() + "%";
            yield return ProgressText; //This does not update as expected.

        }
        yield return null;
    }

发生的情况是,当前项目标签在适当的时间正确更新,但其中的任何内容都不会按预期更新。我能做些什么来使我的小百分比跟踪器对象按照我想要的方式随着每一帧而更新?谢谢!while(!request.isDone)

C# Unity-游戏引擎 while-loop

评论


答:

0赞 hijinxbassist 7/12/2023 #1

返回的异步操作正在执行耗时的部分,而您正在等待它完成。相反,您应该启动请求并使用 while 循环等待它。SendWebRequest

来自 unity 文档:SendWebRequest

在协程中生成 WebRequestAsyncOperation 将导致协程暂停,直到 UnityWebRequest 遇到系统错误或完成通信。

实质上是从请求操作中删除的。yield return

request.SendWebRequest();

while (!request.isDone)
{
    Debug.Log((request.downloadProgress * 100.0f).ToString() + "%"); 
    ProgressText.text = (request.downloadProgress * 100.0f) + "%";
    yield return null;
}

现在,生成发生在 while 循环内部,而不是在请求操作上。如果需要,您可以存储返回的异步操作,尽管我相信请求对象已经足够好了。SendWebRequest

您从 while 循环内部返回进度文本 ui 元素。
请改用 0 或 null 等待下一帧,如上所示。

评论

0赞 1nKy 7/12/2023
这成功了。谢谢!
1赞 derHugo 7/12/2023
@1nKy更进一步:为什么要一个接一个地下载?您甚至可以并行运行它们
0赞 1nKy 7/13/2023
我正在从我的家庭服务器运行下载,该服务器目前只有微不足道的 20Mb 上行链路。所以我尽量不要对我的连接造成太大的负担。我有未来的计划来升级它,但我想从手机游戏中获得一些收入,这是从第一开始的。