Textures memory unmanaged issues

Hi everyone.

I’m porting my game to mobile (i begun with android) and after few days of test i think there’s still a lot of texture memory usage issues which can’t be really resolved. It seems the best i can do is to workaround these issues by bruteforce (example: toss away many textures from the build instead of compress them).

To keep the widest compatibility range with older devices, i don’t want to use ETC2, even because on older devices that will not work.
My problem is that i have actually about 200 textures per level, ending up consuming 500mb of memory, which is totally unappropriate on mobile.

So i tried many ways to reduce the allocation but nothing really worked:

  • I would use atlas and ETC1 + alpha channel compression. But the issue is the atlas will be compressed using ETC2 and once again this isn’t working on older devices. Plus, when i pack a sprite into an atlas, if i need it later to make some runtime operation, i cannot access the single sprite texture, because sprite.texture in that case will return the entire atlas texture.

  • I can’t use RGB o ETC1 compression because i need to preserve alpha channel

  • I could use RGBA 16bit format, but it saves a very little space and the texture quality is ugly

So it seems im condemned to use uncompressed textures. I know 200 textures per level is a huge number on mobile, but its easy to reach it if your level is long and full of details, and cutting off stuff just because there’s no way to shrink it is not the best solution you can achieve.

Some suggestions here would be really appreciated.

Thank you so much!

Make your own shader that take ETC1 + Alpha 8 Mask.
For a 2K atlas that takes 16Mb uncompressed, it takes 2Mb for atlas and 4Mb for Mask(Alpha8 format).
It takes 2.6 times less memory.
Moreover, why do you load all your level at once?If the object using the texture is far away, why do you need the texture?

Also, if it’s a 3D game, try reduce texture size, mobile users won’t notice that your texture is a bit smaller because screens are small and they know mobile is not a PC.

Why don’t you stream the textures from Resources or from the Persistent folder ? Compression should work as well at least on iPhone/Android - We once worked with a project with alot of textures around 15-25 ( 1024x1024 RGB texture ) per level . We ended up compressing them. You can maybe also do diffirent resolutions of the textures and load diffirent sets of textures based on the device ( we did that as well )

What else should i do? I can’t load the texture while the player is approaching it, otherwise the entire game will always load/unload something in real time, causing performance problems. As for drawing, i think Unity handles the frustum culling automatically. I will try the Alpha8 shader, thank you!

I actually use Resources although is not suggested to do it. But Resources folder has so many good points (i came from XNA and its very similar to Content folder of that framework). The issue is that texture atlas wont work with Resources folder. As for streaming textures, i dont really get what you would say: i just cannot load the level meanwhile the user travels across it, otherwise i will have fps dropdown for sure. I need to store about 100~200 textures so the average size of each one must not exceed 1MB usage in memory.

Thank you again :slight_smile:

You really should pack all these textures in an atlas. Having 200 textures is huge on mobile. What kind of game it is? What does it look like? Maybe by seeing what it looks like, we will find what will be best your game.

First of all, thank you for you help :slight_smile:

The game is a simple side scroll platformer.

This is a scene of a single level, for instance.

In this case, im having a lot of gameobjects (>500) each of which contains a sprite renderer to render the tile texture.

Many objects are sharing the same textures, so in this case the total numbers of textures in use is 119.

This is a detail:

This level is totally composed with atlas texture:

But it takes about 10 2048x2048 atlas textures.

Overall, its just another tiled map game, but he’s born on PC and now i’m having hard troubles to shrink it.

Even cutting as much textures as possibile, it still seems too large to fit on mobile. Yes, it runs very well on Samsung Galaxy S6, but i need to target older mobiles (GLES 2.0) as well.

First of all, you should reduce to 1K instead of 2K. Each atlas will be 4Mb instead of 16Mb(uncompressed), it will be far less pressure for the device.

Secondly, are you props in a single texture? I’m mostly talking about the objects int the big tower, like chests and other things.

Finally I don’t understand well your level. You have the sea, then a tower, then a city, then a mountain, I don’t understand the transitions between the different parts of the level. It seems that this is multiple level in one scene.

EDIT: How large is your spiderweb texture?

From 2K to 1K you mean the atlas? Whats the difference in having 10 2K or 20 1K atlas? And there’s a way to specifiy the atlas size?

No, most props are not embedded in the same texture. This is an optimization im doing right now, thus i dont expect big changes in terms of performances. What really hurts the rendering is the transparency and the sprite overlay.

The transitions in level … well, i have many longplay videos about it, this is the level in game, look from 7:39:

I already trimmed a LOT of textures but still im using 119 textures overall for this level (which is one of the biggest in the entire game).

Thank you!

Looks like a nice game!

Nothing what you’re doing looks out of the ordinary and they are standard unity features.

If you keep having problems there should still be no problem why you cannot stream resources as tiles are coming near the screen, you can do that in a background thread and upload the texture to the atlas by using a Realtime texture for atlas instead of a static texture atlas.

The culling Unity does is the most rudimental and you can maybe benefit for writing your own scenemanager system that creates and destroys tiles from a pool of data instead of setting everything up in a scene - look into setting it up in a text file that you can export the scene into.

Thank you crispybeans!

Well, i never tried to stream assets like you’re saying. The level is entirely loaded with all the textures inside, because this is the only way i found to make atlas working: the sprite is referenced in a static field on the object, so the engine detects it as packed sprite and gets the referenced sprite in the atlas. And thats fine for levels, because level is static and textures wont change while the game is playing. The level asset folder is outside the Resources folder.

Different story is for dynamic objects (character, weapons and so on) : they are loaded via Resources at runtime, so at first instance i can’t use atlas. I tried to pull the sprite sheets outside the resources folder, and group them on Sprite list associated to related object (for instance: the player object has a sprite dictionary where i drag n drop the entire sprite list of the player). The issue with that is the sprites are now coming from an atlas, so if i have to split every spritesheet coming from the atlas, i’d need to get the sliced original source texture instead of the whole atlas texture. Sprite.texture unfortunately returns the whole atlas texture when packed. I’d need to use something like SpriteUtility.GetSpriteTexture(), but it works only in editor.

My next attempt will be to use a ETC 1 + alpha8 filter to see if that will decrease memory usage.
This link seems useful:
https://edarvelaez.wordpress.com/2014/01/22/compressing-alphaed-spritesheets-for-android-on-unity-4-3/

As for rendering performance, i think there’s a little i can do, since its really tied to hardware. For example, on a old Mediacom device (3 years old) im getting 20-30fps, on Gamestick console im getting 50fps and on Samsung Galaxy S6 im getting 70 (!!!) fps.

I don’t understand why you say first that you have 200 textures and after you say you only have 10.

Honestly, when I work on mobile, I try to take 720p as base resolution so my atlas never goes bigger than 1024x1024.

We have another game that use a set of SD atlases and HD atlases, but we only have 3 atlases + texture font + some big textures that doesn’t fit in atlases.

Textures take around 123Mb in SD. I don’t think you can port your game by keeping the same scenes. Obviously you need to reuse some textures multiple times to avoid an infinite growing number of textures. For exemple in your level I see you have multiples types of trees. Maybe you could have the same tree at different quality level(size) to avoid having 3 or 4 trees at max resolution(even if they’re blurry)

Also it would be a nice thing to group all the assets that are in the same level, in the same group of atlas. This way you don’t have atlas of level 1 loaded at level 4 because a lamp you use in level 4 is also used in level 1. That will make a duplicate texture, but this way you will not load an entire atlas for one sprite.

You can also check that your scene doesn’t reference useless atlases that you don’t use in this level.

Yeah, my fault, sorry: actually i have like 100~200 textures per level, but these are grouped in atlas. I mentioned 200 because my purpose was to find the best way to manage them in terms of disk space and memory size. Plus, i have other 200 textures for dynamic objects (chars, weapons, bonuses) and these textures cannot be grouped in atlas because are actually spritesheets which i need to trim, so taking em from atlas wont return me the exact sprite texture but the whole sprite texture.
Me too im thinking that i will need to change the scenes completely. Whatever i try to compress data, i’m taking too much room in any case. Thats why i wrote that the only real way to optimize was to toss a lot of stuff. You can spend days trying compression methods, but if the original source is already TOO big, it will never work.