- Home /
PNG on iOS?
According to the editor log, my game is 99.8% textures. It is now almost 500MB. The source images are all PNG format, and clock in at under 45MB. How can I force Unity to use the PNGs as-is on iOS instead of bloating them to ridiculous sizes?
Using PVRTC compression is NOT the answer. Using 16-bit textures is NOT the answer either.
I realize that PVRTC is the native compression for iOS, but my game is a 2D game that needs to be pixel perfect. Compression makes the images completely unusable. Switching to 16-bit only cuts the file size in half, and so much color is lost that again, the images are unusable. My last game was made without Unity, just OpenGL. I know iOS has library functions to natively load a PNG to an OpenGL texture because I'VE USED IT. I'm not concerned with optimizing for performance here, I just want to get my game under the 50MB over-the-air download size limit to maximize downloads. My assets are WELL under 50MB (even with Unity's dlls etc), this should not be a difficult task. I have Unity Pro with iOS Pro. How can this be accomplished? I've only found others with the same problem, but nobody with the answer. Surely this is just a hidden checkbox in Unity's options somewhere, right? RIGHT? PLEASE?
Thanks!
Unfortunately, no automated native support for that pipeline. No 8 bit support either, which is a bit of a bummer.
You can manually load PNGs from script though, and copy their contents to an uncompressed surface. It's a bit of work to do so, and it breaks some of the wysiwyg functionality of the editor, but it's doable.
You could also look at strea$$anonymous$$g Asset Bundles. You'd have to serve them yourself, but you could pare down the initial download to something acceptable play and size wise, and start strea$$anonymous$$g the rest of the game behind the scenes.
Thinking about it... I wonder if you could automate the process a little bit using an Asset Preprocessor.
You could force all your textures to import at tiny size and super low quality there, to act as stubs while you're working in unity. $$anonymous$$eanwhile, you would also copy the original high res PNGs to a resource folder in the background, in a mirrored folder structure.
At runtime, you'd have a script that could check to see what's loaded, and step through each texture, replacing its contents with the original from the resource folder.
I think I might try that out sometime soon.
What about using the lossless PNG files ins$$anonymous$$d of tiny low quality ones? They are actually smaller than the same file compressed to PVRTC! That way the game is still wysiwyg in the Unity editor. Ins$$anonymous$$d of downloading in the background (500mb on someone's data plan if they don't have WiFi? Not good!) just decompress the PNG files to your documents folder the first time you run the game (a one time occurrence with no additional downloading required!). It still seems like a huge pain to fix up all your textures to load from a documents folder, but maybe it can be automated though clever scripting? I'd never want the user seeing the game running with low resolution "temporary" images while it loads the "good" ones...
EDIT: Ack, forgot Unity is going to export the textures to something if you have a material set up on an object, which is what allows you to see it in the editor. You would have to make an export process that detaches all your materials so Unity exports NO textures at all, then re-create the materials somehow at run-time on the iOS side. This could be very challenging without official support from Unity :/
@SuperSquawk, have you found solution for your question?
Answer by Kryptos · Dec 03, 2012 at 01:10 PM
See this page for the texture formats that are supported. PNG are not natively supported (even in Windows), they are always converted to a texture format that is recognized by the hardware (graphic cards do not treat PNG files).
So you need to decrease the size of your images and/or use atlasing to reduce the number of resources used at any time.
You can also take a look at Optimizing Performance in iOS.
Or do what @paulius-liekis suggested. But at runtime, you will still have 500 MB of textures in memory, which may crash your game.
Hi Nicolas!
I appreciate that you are trying to be helpful, but I think you are missing the point. I'm not suggesting I want to send a png directly to video memory as-is. I just want it to be the format used to store my textures on the disk. When the texture needs to be created in OpenGL at runtime, it would be loaded from the png into an appropriate format in video memory (which would be a large uncompressed size). That's fine, I don't need all my textures to be loaded simultaneously. Unity currently allocates and frees textures on the fly as needed and I would expect it to continue doing so. The only difference is when it loads a PNG source image it would use a different loading function to get it into memory. iOS has PNG loading to OpenGL texture functionality built in to the iOS SD$$anonymous$$ API. I'm sure there is some overhead involved, but I'm willing to trade loading time for disk size.
A second option would be for the PNG texture to decompress to a full sized uncompressed file in the app's documents directory on initial launch of the game (something I would also expect to be automatic as an option in Unity), and then load the textures from those generated files from then on (Jetpack Joyride does this on iPad 3, it's a 21.6$$anonymous$$B app, but it creates 160$$anonymous$$B of textures in the document folder. You can check this in the settings app under general->usage.). That is not ideal since it uses up a ton of space on the user's device, but it would have the desired small download size and keep the texture quality and high speed performance. $$anonymous$$aybe that could be an option. Again, I'm talking about a 2D sprite based game here, I absolutely can NOT use compressed textures as it makes the otherwise pixel perfect and lossless png images look terribly blurry. I $$anonymous$$UST use lossless compression like PNG or no compression at all. But I also need the user to be able to download the game without WiFi (meaning it has to be under 50$$anonymous$$B).
Having the same issue here as well! Did you ever find a solution to this?
Answer by Paulius-Liekis · Dec 03, 2012 at 11:05 AM
Unity allows you loading PNGs using WWW class, so maybe you could load your PNG using WWW from local storate. Not most effective way, but should work.
I have not tried it myself but I could imagine there's issues with memory overhead and slow import using the WWW-class for loads of textures. Sorry for nonconstructive comments. :)
Answer by buczek · Feb 18, 2015 at 01:55 AM
I was struggling with this as well and just found image quality settings for Unity 4.6 under Edit->Project Settings->Quality.
More information can be found here: http://docs.unity3d.com/Manual/class-QualitySettings.html
This answer has nothing to do with the question being asked.
The question was, "How can I force Unity to use the PNGs as-is on iOS ins$$anonymous$$d of bloating them to ridiculous sizes?" By going into quality from the project settings, you can change how Unity is compressing images. One of the options is texture quality and from there you can choose full res. $$anonymous$$eeping the PNGs as-is on iOS.
And yet you haven't read that changing quality is not desirable option
File.RealAllBytes will give you a PNG file as-is, the only problem is that you can not use it for rendering. It's not Unity limitation - it's hardware limitation. Hardware doesn't have built in sampling of PNG textures, it has other formats which you're supposed to use.