在 C# for Unity 中非阻塞加载和复制大型 Texture2D [英] Non-blocking loading and copying of large Texture2D's in C# for Unity

查看:38
本文介绍了在 C# for Unity 中非阻塞加载和复制大型 Texture2D的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为 Android 构建一个 Unity 应用程序,它处理动态加载大量大纹理(所有图像的大小都超过 6MB,作为 png 的).这些纹理可以来自 Amazon S3 服务器(在这种情况下它们作为流到达),也可以来自用户的设备本身.

I'm building a Unity app for Android which deals with loading a lot of large textures dynamically (all images are over 6MB in size as png's). These textures can either come from an Amazon S3 server, in which case they arrive as a stream, or from the user's device itself.

在这两种情况下,我都能毫无问题地异步获取原始数据或纹理.第一个我查询服务器并获得数据流的回调,第二个我使用 WWW 类通过file://"协议获取纹理.

In both cases I'm able to get hold of the raw data or texture asynchronously without a problem. In the first I query the server and get a callback with the stream of data, and in the second I use the WWW class to get hold of the texture making use of the "file://" protocol.

只要我想将此数据复制到 Texture2D 到某个我可以使用的地方,例如到 Texture2D 私有成员上,问题就会发生.

The problem happens as soon as I want to copy this data into a Texture2D to some place I can make use of, such as onto a Texture2D private member.

对于流,我将其转换为字节 [] 并尝试调用 LoadImage(),对于 WWW 类,我只需尝试使用 myTexture = www.texture 复制它.两次我都在加载或复制纹理时得到一个巨大的帧.我想根除此框架,因为该应用程序无法随附.

With the stream I convert it into a byte[] and try calling LoadImage(), and with the WWW class I simply try copying it with myTexture = www.texture. Both times I get a massive frame out as the texture is loaded or copied. I want to eradicate this frame out because the App is simply un-shippable with it.

using (var stream = responseStream)
{
   byte[] myBinary = ToByteArray(stream);
   m_myTexture.LoadImage(myBinary);  // Commenting this line removes frame out
}

...

WWW www = new WWW("file://" + filePath);
yield return www;
m_myTexture = www.texture;  // Commenting this line removes frame out

不幸的是,Unity 似乎不喜欢在与主线程不同的线程上运行这些操作,并在我尝试时抛出异常.

Unfortunately Unity doesn't seem to like running these operations on a separate thread from the main thread and throws an exception when I try.

有没有办法将这些操作分块,以便它需要多个帧?或者做一些不会停止主线程的快速内存复制操作?

Is there any way to perhaps chunk up these operations so that it takes multiple frames? Or do some sort of fast memcopy operation that won't stall the main thread?

提前致谢!

PS:我在以下 repo 中创建了一个问题的工作示例:https://github.com/NeoSouldier/Texture2DTest/

PS: I've created a working example of the problem in the following repo: https://github.com/NeoSouldier/Texture2DTest/

推荐答案

最终通过创建一个 C++ 插件(通过 Android Studio 2.2 构建)解决了这个问题,该插件利用stb_image.h"加载图像和 OpenGL生成纹理并将一组扫描线映射到多个帧的纹理上.然后纹理通过Texture2D.CreateExternalTexture()交给Unity.

Eventually this problem was solved by creating a C++ Plugin (built through Android Studio 2.2) that makes use of "stb_image.h" for loading the image, and OpenGL to generate textures and map a set of scanlines onto the texture over multiple frames. The texture is then handed over to Unity through Texture2D.CreateExternalTexture().

此方法不会使工作异步,而是将加载成本分摊到多个帧上,移除同步块并输出后续帧.

This method does not make the work asynchronous but spreads the loading cost over multiple frames removing the synchronous block and subsequent frame out.

我无法使纹理创建异步,因为为了使 OpenGL 函数工作,您需要从 Unity 的主渲染线程运行代码,因此必须通过 GL.IssuePluginEvent() 调用函数 - Unity 的文档使用以下项目来解释如何使用此功能:https://bitbucket.org/Unity-Technologies/graphicsdemos/

I wasn't able to make the texture creation asynchronous because in order for the OpenGL functions to work you are required to be running the code from Unity's main Render Thread, so functions must be called through GL.IssuePluginEvent() - Unity's docs use the following project to explain how to make use of this functionality: https://bitbucket.org/Unity-Technologies/graphicsdemos/

我已经清理了我正在处理的测试存储库并在自述文件中编写了说明,以便尽可能容易地理解我得出的最终解决方案.我希望它在某个时候对某人有用,并且他们不必像我那样花时间来解决这个问题!https://github.com/NeoSouldier/Texture2DTest/

I've cleaned up the test repo I was working on and written instructions in the README to make it as easy as possible to understand the final solution I came to. I hope that it will be of use to someone at some point and that they won't have to spend as long as I've done to solve this problem! https://github.com/NeoSouldier/Texture2DTest/

这篇关于在 C# for Unity 中非阻塞加载和复制大型 Texture2D的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆