Unity3D - 为Android单独开启UI线程

3
在我的Android智能手机VR应用程序中(我认为它是不是VR应用程序都无关紧要),我从Street View下载了6张大图像,并构建了一个skybox。在此过程中,整个应用程序包括环境和UI都会冻结。大约10秒后,进程才会结束, Street View才会出现。
如何将主处理与UI分离?因此,手机正在工作,但不应该冻结。这是常见的Web问题,但我该如何在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;
}

你目前在使用什么代码? - Fredrik Schön
我将代码放入帖子中`private byte[] GetStreetviewTexture(string url) { WWW www = new WWW(url);while (!www.isDone) ; if (!string.IsNullOrEmpty(www.error)) { Debug.LogWarning("无法下载纹理: " + www.error); } else { bytes = www.texture.EncodeToPNG(); } return bytes;}` - fmielke
1个回答

1
你可能需要使用IEnumerator将其与Unity Coroutine一起线程化。如果您已经在使用它,我假设您确实在使用它 - 它是否可能是导致设备冻结的性能问题?如果是这样,请检查 Unity profiler和/或 Unity Remote。协同程序不像评论所建议的那样是一个线程,而是模拟了线程行为。
基本的Coroutine代码:
void SomeMethod() {
    StartCoroutine(Threaded());
}

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

请查看WWW类以及如何使IEnumerator等待下载完成


回应 OP 的跟进问题更新:

如何判断 Coroutine 已完成并获得值


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

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,并且我不知道您是否使用按钮来启动纹理设置。这可以是任何类型的触发/起始点。

正如您所看到的,我需要在此方法中返回byte[]字节数组。您有任何使用Coroutine返回值的想法吗?@Fredrik - fmielke
我的回答是:协程,这就是你在寻找的吗?当然,这是我通常在协程中使用回调的方法:http://stackoverflow.com/questions/41445427/how-to-use-a-value-from-a-coroutine-or-tell-when-its-done/41445428#41445428。将“Action<string>”更改为“Action<byte[]>”,你就可以开始了! - Fredrik Schön
好的,那个方法可行,但是冻结问题仍然存在。现在我尝试将只有www下载部分放入Corotuin中。我将其外包为“answer”,因为在评论中没有足够的空间@Fredrik。 - fmielke
从我现在所看到的情况来看,它应该是可以工作的。为了帮助您理解流程,我打开了画图并绘制了一些内容:http://imgur.com/a/60sIm - Fredrik Schön
这张图片很棒,非常感谢。不幸的是,它因所描述的行为而无法使用。也许这真的是我的循环问题,它目前在代码上看不到。我又更新了我的“答案”。 - fmielke
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接