首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Texture2D.LoadImage异步

Texture2D.LoadImage异步
EN

Stack Overflow用户
提问于 2021-09-11 00:15:42
回答 2查看 1.1K关注 0票数 2

简单而简短的问题,

我从服务器上下载了一个纹理(185MB纹理图集)。但是使用Texture2D.LoadImage创建字节之外的纹理会阻塞应用程序大约4秒。如何异步创建此纹理?

代码语言:javascript
运行
复制
// Load texture atlas texture data
HttpWebRequest atlasTextureRequest = WebRequest.CreateHttp(EntityDatabase.ATLAS_TEXTURE_PATH);
WebResponse atlasTextureResponse = await atlasTextureRequest.GetResponseAsync();

byte[] atlasTextureData = await EntityDatabase.ReadStreamAsync(
    atlasTextureResponse.GetResponseStream(),
    (int)atlasTextureResponse.ContentLength
);

EntityDatabase.TextureAtlasTexture = new Texture2D(1, 1);
EntityDatabase.TextureAtlasTexture.LoadImage(atlasTextureData);
EN

回答 2

Stack Overflow用户

发布于 2021-09-11 03:43:16

操作:

如何异步创建此纹理?

简短的回答

你不能,

更长的答案

通过.NET 4.x为我们带来async/await支持允许异步I/O和异步计算。一般来说,它们的使用没有障碍,但在Unity 3D 中有,特别是compute。

下面的代码是受I/O限制的,并且是异步I/O的一个例子,Unity不应该对此有任何疑虑。造成问题的部分将是你的纹理创建。继续往下读。

代码语言:javascript
运行
复制
WebResponse atlasTextureResponse = await atlasTextureRequest.GetResponseAsync();

byte[] atlasTextureData = await EntityDatabase.ReadStreamAsync(
    atlasTextureResponse.GetResponseStream(),
    (int)atlasTextureResponse.ContentLength
);

在Unity中创建纹理是受CPU限制的,并且是计算操作的一个示例。要在后台执行计算操作,通常需要执行以下操作:

代码语言:javascript
运行
复制
var stuff = 
    await Task.Run (() => ConstructSomethingThatTakesALongTimeSynchonosouly ();

...which很好,但是我们想要创建一个Texture2D,所以我们可以尝试这样做:

代码语言:javascript
运行
复制
public class LoadTextureAsyncExample : MonoBehaviour
{
    // Start runs in the main thread
    private async void Start()
    {
        var textureBytes = await DownloadTextureAsync();
        _texture = await Task.Run(() => CreateTexture2D(textureBytes));
    }
 
    private async Task<byte[]> DownloadTextureAsync()
    {
        // essentially your code above.  
        // This method will be a mixture of main/pool thread
    }

    private Texture2D CreateTexture2D(byte[] textureBytes)
    {
        // this method is running in a thread pool thread
        var texture = new Texture2D(1, 1);
        texture.LoadRawTextureData(textureBytes);
        return texture;
    }

...now虽然CreateTexture2D将在线程池线程中运行,并且不会阻塞主线程,但代码将在创建Texture2D时失败,因为它运行在与主线程不同的线程中。

必须在主线程中创建由C#创建的纹理。您可以尝试设置Texture.allowThreadedTextureCreation = true,但这也不起作用。Unity在下面说得最好。

统一(我的重点):

Texture.allowThreadedTextureCreation Description允许统一内部在任何线程(而不是专用渲染线程)上执行纹理创建。注意:用于创建纹理的C#应用编程接口(例如,新Texture2D)必须始终在主线程上调用。此设置不会更改该requirement.

票数 1
EN

Stack Overflow用户

发布于 2021-09-11 07:55:29

Micky's answer上扩展

目前,加载纹理的唯一内置(不需要额外的本机代码)非阻塞方式是使用

Coroutine中的UnityWebRequestTexture.GetTexture

API中的示例

代码语言:javascript
运行
复制
void Start()
{
    StartCoroutine(GetText(SOME_URL));
}

IEnumerator DownloadTexture(string url)
{
    using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture(url))
    {
        yield return uwr.SendWebRequest();

        if (uwr.result != UnityWebRequest.Result.Success)
        {
            Debug.Log(uwr.error);
        }
        else
        {
            // Get downloaded asset bundle
            var texture = DownloadHandlerTexture.GetContent(uwr);
        }
    }
}

这也适用于设备上的本地文件路径。

如果不能直接这样做,您仍然可以将临时文件异步下载并存储在您的设备上,然后使用UnityWebRequestTexture.GetTexture加载本地存储的文件,然后再次删除本地文件。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69139083

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档