【问题标题】:unity3d - Separate UI Thread for Androidunity3d - Android 的独立 UI 线程
【发布时间】:2017-06-12 00:37:31
【问题描述】:

在我用于 Android 智能手机的 VR 应用程序中(我认为它是否是 VR 应用程序并不重要)我从街景中下载了 6 张大图像并用它构建了一个天空盒。在此过程中,整个应用程序包括。环境和 UI 冻结。大约 10 秒后,进程停止,街景就在那里。

如何将主处理与 UI 分开?所以电话可以工作,但不应该冻结。这是一个常见的网络问题,但如何在 Unity for Android 中解决这个问题?

谢谢!

代码:

private byte[] GetStreetviewTexture(string url) {
WWW www = new WWW(url);

while (!www.isDone) ;

if (!string.IsNullOrEmpty(www.error))
{
    Debug.LogWarning("Unable to DL texture: " + www.error);
}
else
{
    bytes = www.texture.EncodeToPNG();
}
return bytes;
}

【问题讨论】:

  • 你目前使用的是什么代码?
  • 我把代码放到帖子里`private byte[] GetStreetviewTexture(string url) { WWW www = new WWW(url);而 (!www.isDone) ; if (!string.IsNullOrEmpty(www.error)) { Debug.LogWarning("Unable to DL texture:" + www.error); } else { 字节 = www.texture.EncodeToPNG(); } 返回字节; }`

标签: android multithreading user-interface unity3d


【解决方案1】:

您可能希望使用 IEnumerator 将其与 Unity Coroutine 连接起来。如果您已经在使用它,我假设您实际上是 - 这可能是冻结设备的性能问题吗?如果是这样,请检查Unity profiler 和/或Unity Remote。正如 cmets 建议的那样,协程不是线程,而是模拟线程行为。

基本协程代码:

void SomeMethod() {
    StartCoroutine(Threaded());
}

IEnumerator Threaded() {
    // Do something
    yield return new WaitForSeconds(3f);
}

查看WWW class 以及如何让 IEnumerator 等待下载完成


更新回应 OP 的后续问题:

How to tell when a Coroutine is done and get a value


更新响应 OP 后续跟进问题: 这是您当前逻辑/流程的简化示例。 注意:这不起作用不要将此代码用作应该如何完成的示例,我只是想说明您应该如何解决问题的差异。

void ButtonClicked() {
     SetTexture()
}

void SetTexture() {
    Texture texture = GetTexture()
    Object.texture = texture;
}

Texture GetTexture() {
    Texture texture;
    StartCoroutine(DownloadTexture((textureCallback) => {
        texture = textureCallback;
    }));
    return texture;
}

IEnumerator DownloadTexture(Action<Texture> callbackTexture)
{
    WWW www = new WWW(URL);
    yield return www;

    callback(www.texture);
}

这不仅不起作用,因为协程与其余代码异步运行,而且它不是完成此任务的好方法。

而不是做

按钮点击->设置纹理->开始下载->错误设置纹理->下载完成

你想要的:

按钮点击->下载纹理->等待完成->设置纹理

像这样:

void ButtonClick() {
    StartCoroutine(DownloadTexture((callbackTexture) => {
        SetTexture(callbackTexture); // Will run SetTexture when Coroutine DownloadTexture is completed.
    }));
}

IEnumerator DownloadTexture(Action<Texture> callbackTexture)
{
    WWW www = new WWW(URL);
    yield return www;

    callback(www.texture);
}

void SetTexture(Texture texture) {
     object.texture = texture;
}

请注意,这只是流程代码。您的代码看起来会有所不同,使用 byte[] 而不是 Texture,我不知道您是否使用 Button 来启动纹理设置。这可以是任何类型的触发/起点。

【讨论】:

  • "使用 IEnumerator 来线程化" 协程不是线程。 WWW 在另一个线程中运行并提供了一个函数来产生它,但协程不是线程。 “使用 IEnumerator 等待 WWW”本来是合适的,但如果没有 OP 的代码,我们无法判断发生了什么。
  • 对,但它模拟了线程行为——我最初认为 OP 想要的。我设法不阅读粗体字......
  • 我认为我的回答可能适用...我认为这不是您需要的线程性能提升,只是稍微增强的代码。尝试改用协程,就像 WWW-class 文档中的示例一样。
  • 如您所见,我需要在此方法中返回 byte[] 个字节。你有什么想法用 Coroutine 返回一些东西吗? @弗雷德里克
  • 是我的回答;协程,你在找什么?当然,这就是我通常在协程中使用回调的方式:stackoverflow.com/questions/41445427/…。将 Action&lt;string&gt; 更改为 Action&lt;byte[]&gt; 就可以了!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多