Search code examples
androidunity-game-enginetexture2d

Erratic errors loading image with Texture2d.LoadImage(byte[]) on Android devices


I have an app which has to create Sprite-instances on the fly based on data contained in byte arrays (PNGs and JPGs). The following code is used to create the sprites:

Texture2D texture = new Texture2D(2, 2, TextureFormat.RGBA32,false,false); 
texture.LoadImage(data);
Vector2 pivot = new Vector2(0.5f, 0.5f);
Rect tRect = new Rect(0, 0, texture.width, texture.height);        
return Sprite.Create(texture, tRect, pivot);

This works fine, however, depending on the device and the size of the images, after a random number of images, the app freezes and then will be shut down by the OS. Its always another image, which fails. Also, the data source is irrelevant.

Looking into the logs of the app via adb shows nothing. If I write to the debug log, I can see, that the last statement which gets called is texture.LoadImage. However, there is no exception or another information about the error. Catching the exception does also not work.

The error does not occur in the editor. The error occurs on the android devices (2) in development build and in production build.

Searching the web, I found the below entry, which states the very same problem, but no solution has been posted (they circled around the www-part, however the problem is not with that):

https://forum.unity.com/threads/android-crash-when-using-multiple-www.483941/

UPDATE

One interesting finding is, that if I set the markNonReadable-Parameter of the texture.LoadImage() method to true, the error occurs less frequently, but still is there.

texture.LoadImage(data,true);      

Solution

  • Textures are not garbage collected. So if you create a texture using new Texture then you need to destroy the texture with Destroy(texture) when you no longer need it. I believe Sprite object also needs to be destroyed. In your case, textures that were loaded stayed in memory until Android OS closed your app because of memory pressure. UnloadUnusedAssets() should also destroy all the textures and sprites that are no longer referenced, but it takes a lot of time (about 1 second), so it only makes sense to call that when changing scenes.