I’m in the process of optimizing my application memory consumption.
In the process, I’m using Unity profiler while connecting to an Android device, which run a development build of the application.
The application, is using two types of sprite containers:
Sprite sheets created by the Texture packer.
Sprite Atlases created by unity.
Using the profiler, it is observed that while the sprite sheets (created by the Texture packer) take the expected amount of RAM, the sprite atlases created by unity consume DOUBLE the expected amount of RAM.
For example, the sprite atlas UIATLAS, whose size is 4096x4096 is supposed to consume 16MB of RAM:
But looking at the profiler, after running “Take Sample”, you see the value 32MB:
One more comment (please review): UIAtlas belongs to an asset bundle called “atlas_ui”. It is defined on several directories containing its sprites, all of which belong to the same asset bundle, atlas_ui. Is that the correct way to define it?
Read/Write Enabled means the texture is in GPU memory and retained in CPU memory after upload to the GPU, hence taking twice the space. Unless necessary, Read/Write should always be disabled.
You wouldn’t I guess. It’s kept in CPU so it is readable and if written to can get re-uploaded. Unless you need to read pixels from the atlas or modify them.
After uploading, yes. It will pass through CPU memory for uploading it to the GPU driver memory. So while uploading, it’s in memory twice but afterwards only in the GPU driver memory.
Mipmaps do take up more space, but only 33% more, not 100% more.
Having them enabled can improve performance and image quality, so it is often a bad idea to turn them off (but not always, it should be tested in each case).
One more thing; For one of the atlases, I need to use GetSprites(). To do that, the atlas must be set as ReadWrite enabled.
If GetSprites() is done only during initialization, right after loading the spriteatlas from asset bundle, is it safe to change the atlas settings to disable ReadWrite? How do I do that?
If instead of using Unity SpriteAtlas, I use Texture Packer to create an atlas with its tpsheet, I can still get a reference to its sprites and set them in sprite renderers individually, without the RAM penalty using Unity SpriteAtlas. Any downsides I don’t see here?
Solved it, description:
Since I only need the references to the sprites and not the textures themselves, I am loading the sprites from the asset bundle and disabling ReadWrite for the atlas. This way, duplication is removed for both the GetSprites (which clones the sprites) and for saving the spriteatlas in CPU memory space.
If you are loading the sprite directly from asset bundle, the atlas is not needed. Your build will include both the Sprite and its atlas, but you only use the Sprite. You should remove the atlas
Sorry to bring up this old post but Im curious about the usage of atlases in this case… do you actually save any ram performance by creating atlases? or it would be exactly the same using separated sprites?
Atlases often take-up more RAM/VRAM because they almost always contain some empty space.
Saving memory was never the purpose of using an atlas. The point of using an atlas is only to reduce the amount of materials that the renderer has to set-up. This can result in better performance depending on your scene.
Well, the memory consumption also depends on the sizes and form factors of the individual sprites and compression Algos used. The latter often don’t work on NPOT resolutions, while atlases will usually be POT resolutions. So the added extra padding might no end up actually costing anything while allowing for better compression
What I thought it could be useful in some contexts is to have the atlases are grouped by usage so for example lets say we have a set of textures that are just used in certain popup or certain scene… we could use addressables or Resources.Unload and just load or unload that atlas from memory when we enter/exit that popup or scene or whatever, would this be a correct use?
My version “correct use” is to avoid micromanaging memory usage if possible (unless my memory consumption is actually causing a problem).
If you’re loading and unloading lots of different scenes with unique assets, I guess it might be good to call Resources.UnloadUnusedAssets occasionally. So far I haven’t made a project big enough where this was necessary.
Also, read what MartinTilo wrote. You’ll see the answer’s not really clear at all. Always be suspicious of “clear answers,” they’re usually just over-simplifications.