My game is generating a lot of textures at runtime, and storing them in StreamingAssets for loading later. For loading the textures, I’m using the example setup from the documentation:
fileData = File.ReadAllBytes(path);
tex = new Texture2D(2, 2);
tex.LoadImage(fileData);
}```
The total execution time for loading five 1024 textures via this method is over 60ms! If I create a material with the five textures on it for testing and load the prefab at runtime, the execution time is <1ms. Both methods need to load the texture data, so where is the huge difference coming from? How can I speed things up?
How do you load the prefab? Most likely it was already loaded when the scene containing a reference to it is loaded.
Native textures in Unity are already compressed for the GPU and can be immediately uploaded, LoadImage
needs to decode the image, maybe apply some processing and upload it to the GPU, which is going to take longer. Checking with the profiler should give you a better idea where exactly the time is spent.
Using asset bundles should make the loading more comparable to that of embedded textures, the texture data can then also be directly uploaded to the GPU and Unity can probably offload a bit more to other threads.
Asset Bundles look like they can only be created in the editor, however I am creating my textures (and models) at runtime. Are there other options? Or is there a way to save my textures as native textures?
I don’t believe Unity compresses files in StreamingAssets folder. Unity - Manual: Streaming Assets
The unique nature of streamingassets I believe leaves those files all original, thus they don’t have import settings.
That being said, I suggest looking into addressables/asset bundles perhaps. Even the link above mentions those are preferred.
On most platforms, you can’t save to streamingassets (even mentions that in the link). I’m not sure I understand your flow in creating these textures. Where are you getting the data from? Are you downloading something from the internet and saving it locally?
My textures are generated from a couple hundred parameters passed into a complex shader at runtime and then blitted into a png, which I save into StreamingAssets. I don’t think AssetBundles or Addressables are right for my use-case as both require pre-configuration in the editor.
Whether StreamingAssets or PersistentDataPath (the recommended alternative), it doesn’t really matter either way in my case. I guess the question at this point has really become: is there any way to prepare a PNG for saving at runtime with Unity’s compressed image format in order to support fast loading?
Not a PNG, because that’s by definition a different format and not supported by the GPU. There’s Texture2D.GetRawTextureData and Texture2D.LoadRawTextureData, which you could use to save the raw texture data but then you’ll have to manage the different texture formats manually.
I also saw UnityAsyncImageLoader, which purportedly does the same as ImageConversion.LoadImage
but is offloading it to another thread (note the troubleshooting question at the bottom about stalling if the texture is accessed too early).