【问题标题】:Unity3D, yield return www blocking main thread in iOSUnity3D,yield return www阻塞iOS中的主线程
【发布时间】:2015-09-20 21:52:54
【问题描述】:

在通过 Unity3D 创建 iOS 64 支持的过程中,我遇到了一个奇怪的情况, yield return www 调用阻塞了设备上的主线程。

我尝试了 Unity 版本 4.6.5、4.6.6 和 5.1.0,并在 WWW 类中遇到了同样的问题。 我也试过 xCode 版本 6.3.0、6.3.1、6.3.2。

下面是我正在使用的代码sn-p

private IEnumerator StartDownload(string url, string path)
{
    WWW www = new WWW(url);
    yield return www; //blocking main thread
    if (string.IsNullOrEmpty(www.error))
    {
        Debug.Log("File Download Complete");
    }
    else
    {
        Debug.Log("Error in downloading file, Error: " + www.error);
    }
}

【问题讨论】:

    标签: ios web unity3d coroutine


    【解决方案1】:

    我从未见过 yield return www; 阻止整个下载,但我确实遇到过:

    • 如果您要下载大型资产(超过几兆)
    • 并具有快速的互联网连接(超过 2 MB/s)
    • 您会看到 UI 线程冻结

    发生这种情况是因为即使在 Unity 将数据从下载缓冲区复制到最终位置时下载发生在不同的线程上,复制也是在 UI 线程完成的,如果磁盘操作超过 2 MB/s,那么线程被阻塞了。

    该错误存在于 iOS 的 Unity WWW 实现中。 如果这是您的情况,我可以为您提供我为解决此问题所做的更改。

    【讨论】:

    • 我编写的代码在 Android 和 Unity 编辑器上运行良好,它只在 iOS 中产生问题。我对资产包缓存的主要关注,当我调用 yield return WWW.LoadFromCacheOrDownload(path, 1) 帧速率冻结几秒钟,资产包大小分别为 18 和 22 MB。找到示例代码link
    • 是的,它只发生在 iOS 上,因为 iOS 上的实现不同。我已经反编译了 android 的 WWW 源代码,实现解决了这个问题,这就是为什么你没有问题
    • @RaduDita 你的修复是什么?关心发布它们吗?那真的很有帮助!
    • 我可以挖掘我所做的修复,但它们不适用于最新的 Unity 版本。负责复制数据的代码是从objective-c 移到一个封闭源dll 中的,我没有找到解决办法。
    • @RaduDita 我明白了。但是为了记录,可以通过使用 WebClient.DownloadFileAsync() (stackoverflow.com/questions/29707709/…) 和 AssetBundle.LoadFromFileAsync() (docs.unity3d.com/ScriptReference/…) 来解决它
    【解决方案2】:

    我能想到它阻塞主线程的唯一方法是,如果你没有正确地将它作为协程调用......

    正确的调用:

    void Start()
    {
        StartCoroutine(StartDownload("http://google.com", ""));
    }
    

    然后调用延迟运行(在主线程中),但不会阻塞线程。它将被轮询直到完成。

    方式不正确(会阻塞主线程):

    void Start()
    {
        IEnumerator a = StartDownload ("http://google.com", "");
        while (a.MoveNext()) {}
    }
    

    【讨论】:

    • 嗨@peterept 我正在使用 StartCoroutine(StartDownload("google.com", ""));问题仅出在 iOS 上,在 Android 中,Unity Editor 相同的代码运行良好。 iOS 的任何帮助。
    • 请查看示例代码link
    • 我一直在 iOS 上构建,并使用您提到的所有 Unity 版本。 (尽管在 Xcode 上不是您提到的 6.3 版本)。但我建议如果协程在 iOS 上中断,将会有很多应用程序受到影响。你能澄清一下“阻塞主线程”是什么意思吗?阻塞意味着没有运行,您可以通过在调试器中按暂停来轻松检查。但也许你只是被某个地方的 Time.timescale = 0 设置“冻结”了?
    • 嗨@peterept。我不知道,我做错了什么,但相同的代码一直工作到 Unity 版本 4.6.2,更新到版本 4.6.5 后,我们遇到了这个问题。对于不超过 2 MB 的小文件没有问题,但如果我开始文件大约 20 mb。帧速率一直卡到缓存未完成。请看代码link。我对 Asset Bundle Caching 的主要关注,当我调用 yield return WWW.LoadFromCacheOrDownload(path, 1) 帧速率冻结几秒钟
    • 感谢您的链接。问题是你有一个 50MB 的资源包,其中包含 3235 个资源,Unity 需要时间来保存该文件并在解析包时处理索引。为了保存这么大的文件,你可以自己写成块,或者将包拆分成多个包。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-01
    • 2018-02-16
    • 1970-01-01
    • 2015-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多