Tasharen Entertainment Forum

Support => NGUI 3 Support => Topic started by: adramanto on January 29, 2014, 03:16:38 PM

Title: Sprite Atlas Broken on IOS (Fixed)
Post by: adramanto on January 29, 2014, 03:16:38 PM
Unity Version: 4.3.1f1
NGUI Version: 3.0.8f6

Recently encountered a problem where the sprite atlas suddenly broke on IOS Builds but was still fine on Android. By broken, I mean that all sprites were either not showing up or displaying a really messed up texture. It turned out that in the texture import settings there was an IOS override that was capped out at 1024 and set to 16 bit. Turning off "Override for Iphone" on the sprite atlas seemed to solve the issue.

Just a general note that having texture overrides seems to break the atlas for IOS if the texture becomes larger than the capped size. Not sure if this is true for any other platforms but turning off the override in the texture import settings fixed the problem.

Title: Re: Sprite Atlas Broken on IOS (Fixed)
Post by: Khan-amil on May 14, 2014, 08:24:11 AM
Kind of old thread, but the issue is still here, so helped me see what was wrong.
Is there any way NGUI could change this settting when creating the atlas texture?
Title: Re: Sprite Atlas Broken on IOS (Fixed)
Post by: ArenMook on May 14, 2014, 11:06:04 PM
If there is any way to choose the override settings via code, I'm not aware of it.
Title: Re: Sprite Atlas Broken on IOS (Fixed)
Post by: psngui on September 12, 2014, 12:17:29 AM
I know that this is an old thread. But we are experiencing the same problem.

It happens not only when making iOS builds with override checkbox ticked, but also when reloading the scene after reducing Max Size in the Default tab of atlases. Note that it only happens when the size is made small enough.

It seems to us that NGUI doesn't pick up such changes made to atlases. Or to be more specific, the UVs of sprites are not updated when such changes are made.

Could you please have a look at the problem, ArenMook?

Not sure if this is related, but here are our settings in the UIRoot:
Scaling Style: FixedSize
Manual Height: 2048
Shrink Portrait UI: Unticked
Adjust by DPI: Unticked

Cheers,
Title: Re: Sprite Atlas Broken on IOS (Fixed)
Post by: ArenMook on September 12, 2014, 04:11:07 AM
Unity can force change import settings of textures, and in some cases there is no way to determine that Unity did that, at least not through code. When an atlas is imported at lower dimensions than its native size, it breaks NGUI's functionality as sprite coordinates are specified in pixels, not UVs.
Title: Re: Sprite Atlas Broken on IOS (Fixed)
Post by: beermoney on September 12, 2014, 06:26:13 AM
I'm curious, why is the UV in pixels not float?  if they were float:[0,1] then it would work irrespective of the atlas size
Title: Re: Sprite Atlas Broken on IOS (Fixed)
Post by: ArenMook on September 13, 2014, 03:20:19 AM
There are a lot of reasons. From readability in inspector to knowing native sprite dimensions, to having sprite's padding and border be specified in the same coordinate space as texture coordinates. NGUI 2 had a mess with both UVs and pixels, and it was a pain to work with and modify.
Title: Re: Sprite Atlas Broken on IOS (Fixed)
Post by: psngui on September 17, 2014, 08:08:29 PM
Hi ArenMook,

Thanks for taking time to view and answer my question.

Is it possible to add a 'manually update atlas' button in Atlas Maker, so that when it's clicked it updates everything in the atlas with the current import settings? I reckon it will solve the problem that NGUI can't automatically pick up the import settings changes done in Unity.

The button will be handy even if it's not for import settings. The way we got around with the problem was to down-size all the images. But to update the atlases, we have to hand-pick all images which is time consuming and error pruning. An "Update All" or "Update Atlas" or "Recreate Atlas" button will be very handy in this case.

Cheers,
Title: Re: Sprite Atlas Broken on IOS (Fixed)
Post by: ArenMook on September 18, 2014, 03:21:10 PM
You have full access to the data inside the UIAtlas (UIAtlas.spriteList). You can loop through it and change it as you see fit, including adjusting it based on some texture size.
Title: Re: Sprite Atlas Broken on IOS (Fixed)
Post by: psngui on September 22, 2014, 07:22:06 PM
Hi ArenMook,

Thanks for the suggestion.

I wouldn't mind trying to fix the problem by myself. Your direction will be helpful. But the thing is that with my own modifications to NGUI there is long term impact on the project. If a new NGUI version is out with some feature we really need, we'll have to do the merge, which can be both time consuming and error pruning.

The request I made is not only an improvement of NGUI, but also a fix to known problems. Would you please consider implement it and include it in official NGUI builds?

Cheers,
Title: Re: Sprite Atlas Broken on IOS (Fixed)
Post by: ArenMook on September 23, 2014, 11:10:35 AM
This wouldn't change NGUI. This would be your custom script modifying the sprite list of an atlas based on your code that's custom to what you're trying to do. You wouldn't be modifying a single NGUI script here, just making your own.
Title: Re: Sprite Atlas Broken on IOS (Fixed)
Post by: psngui on September 24, 2014, 07:06:19 PM
Could you give me some details on how to do it so that no NGUI code is modified? I'd like a button somewhere in Unity so that when it's clicked, the chosen atlas get fully refreshed/updated/regenerated.

Also could you let me know how I can deal with the override settings of atlases? Is that something I can do without modifying NGUI code? Batch downsizing all the images in the game is just a temporary workaround. Ultimately we'll need full sized images to work. It means the override settings need to be working.

Cheers,
Title: Re: Sprite Atlas Broken on IOS (Fixed)
Post by: ArenMook on September 25, 2014, 06:59:10 PM
What override settings? Not sure what you mean.

Create an editor script where you will choose an atlas you want to modify, then loop through the sprites of that atlas and change the data within. Don't forget to mark the atlas object as dirty. Not sure how else to explain this...

This is no different than working with any list in your own script. You have a list. Loop through it, change the data inside. What's so difficult about it? Why do you think you need to modify the List<> class to edit the items within it?
Title: Re: Sprite Atlas Broken on IOS (Fixed)
Post by: psngui on September 25, 2014, 07:56:26 PM
Please check the attached image for what the override settings of atlases are. This is the main problem what this thread is talking about.

The main reason I asked about how to do it is because I'm not experienced in NGUI, and Unity. I wouldn't even understand what your solution (the editor window) means if I haven't luckily enough run into and learned about editor window two days ago. But anyway, thanks for the help.
Title: Re: Sprite Atlas Broken on IOS (Fixed)
Post by: ArenMook on September 25, 2014, 08:01:13 PM
You shouldn't do anything with the texture import settings. They should remain at their largest possible size, otherwise NGUI's sprites will break as the dimensions are specified in pixels, not texture coordinates as I mentioned before. No, there is no automatic handling of downsized textures, because I am pretty sure there is no way to determine what the actual real size of a texture is. When Unity downscales it, it doesn't keep any info on what the original size was.
Title: Re: Sprite Atlas Broken on IOS (Fixed)
Post by: psngui on September 29, 2014, 10:36:37 PM
The problem with largest size is that our game runs out of memory on iOS. We have to downsize all the textures manually (without using the override settings), and manually refresh the atlas to make it work. We considered it as a temporary workaround and was looking for an official solution. Are you saying that there is nothing NGUI can do about it?

EDIT: There seems to be miscellaneous information in .meta file of atlases (.png), e.g., maxTextureSize. Maybe worth a look?
Title: Re: Sprite Atlas Broken on IOS (Fixed)
Post by: ArenMook on September 30, 2014, 04:22:16 AM
Max texture size is just the maximum allowed texture size on import.

If you are running out of memory, reduce your texture usage. Many people have massive atlases full of epic size full screen textures. This is obviously quite ridiculous. Keep large textures outside atlases. Atlases are for small textures. Likewise, keep long / narrow sprites outside atlases as well. If you have a sprite that's 1000x32 for example, then you're doing it wrong. Very wrong. Take advantage of 9-slicing and layering components on top of each other in order to get the look you want instead.
Title: Re: Sprite Atlas Broken on IOS (Fixed)
Post by: psngui on October 01, 2014, 02:20:34 AM
Hi ArenMook,

I just did a file comparison on an atlas between before and after applying override settings of iOS and here are my findings:

1. One (and only file) is changed: the atlas (.png.meta) file.
2. textureFormat is changed from 5 to -3
3. textureSettings/aniso is changed from 4 to 1
4. nPOTScale is changed from 1 to 0
5. buildTargetSettings is changed from [] to the followings:
- buildTarget: iPhone
  maxTextureSize: 4096
  textureFormat: -3
  compressionQuality: 50

All I did was ticking the Override for iPhone then clicking Apply, in which case Max Size is 4096. If Max Size is changed to say 1024, then it will be 'maxTextureSize: 1024' in the .png.meta file.

I believe this information is sufficient for NGUI to update atlases accordingly.

I know that UnityEditor.Callbacks.PostProcessScene can be used to get notified just before a scene is built. According to the doc, BuildTarget and/or RuntimePlatform can be used to determine target platform (I'm not sure about this one). It seems that an automated process can be added to NGUI to generate iOS (or whatever platform with overridden settings) atlases using the override settings.

If that's not possible, at least a manual process (a button for example) can be added to fulfill the need.

Please let me know if any of these is possible.

Title: Re: Sprite Atlas Broken on IOS (Fixed)
Post by: ArenMook on October 01, 2014, 05:19:49 PM
1. I don't care what the max texture size is. I need to know the original texture size, not the max texture size.

2. You are assuming users have text-based metadata files, which is wrong by default. Default is binary.
Title: Re: Sprite Atlas Broken on IOS (Fixed)
Post by: psngui on October 01, 2014, 08:06:19 PM
There is a default maxTextureSize value, and there is an override maxTextureSize value.

With the two values, we can update atlases in these steps:
1. Calculate the ratio of the override value against the default value. Typical values can be: 1/2, 1/4, 1/8, etc.
2. Iterate through all the atlases and do the following steps
   a) Iterate through all the sprites in the atlas
   b) For every sprite, find the relevant source image file, resize it (create new may be a good idea) with the ratio calculated
   c) After all the image files are generated, recreate the atlas with the new image files

To solve that binary/text-based problem, you just have to add a line in NGUI readme file or web page, something like this: If you are going to use Override settings on atlases, you have to enable xxxxxx, which is located at xxxxx. I'm sure you can come up with much better way of saying it.

There is a reason why Unity provide override settings for atlases: some projects, including ours, want to manage images in a way that they are suitable for high-end devices, with the capability to downscale to fit low-end devices, in a convenient way; or in other words, there is only one copy of all the images and they are in highest resolutions.

The mess-up of UI when using atlas' override settings is a bug (or an incomplete feature) of NGUI. I'd think as the author of NGUI, you'd care to perfect your product. (I think NGUI is great, by the way.) However, if you are too busy or reluctant to do it because maybe only a few people use this feature, it will be appreciated if you can validate my theory so that I can do it myself.

Thanks.
Title: Re: Sprite Atlas Broken on IOS (Fixed)
Post by: ArenMook on October 02, 2014, 10:05:55 PM
Once again... I don't care what the "max texture size" setting is. Nor what the override "max texture size" setting is.

Imagine this scenario. You have a 1740x1100 texture. Yes, odd dimensions like that. You import it into Unity. Your desktop's quality is set to a high setting, but still by default that texture gets imported as 2048x1024 because Unity will want it to be power of two unless you change it. The "max texture size" is 2048 by default.

So now you get this texture into your game and realize that it's not proper size. Alright, change the import settings: allow NPOT. Now the texture is correctly 1740x1100.

Now you want this same thing on a mobile device. But hey, you set the texture to be compressed, and on a mobile device that means PVRTC. PVRTC can't do rectangular textures. They must be square. So now your texture gets imported as 2048x2048.

Queue in another android device that can't do 2048, or simply targeting GLES 1.1. Your texture is now 1024x1024. You can choose to override the texure import settings for android to turn off the compression to make it possible to have a rectangle, but then not all devices may get supported. You may also choose to override it to simply change it to something else. Regardless, this doesn't help you figure out what the texture's original size (1740x1100) was from code.

Are you following me now?
Title: Re: Sprite Atlas Broken on IOS (Fixed)
Post by: xod on October 06, 2014, 11:51:27 PM
Your scenario is flawed.

I dont care about full screen textures. I dont care about rectangular textures. I dont care about odd pixels dimensions. I care about all the sprite coordinates getting messed up when using alternate mip levels of a 4096x4096 texture because all your code uses pixel coordinates.

Packing textures at max res is a great idea, because devices that can handle those size textures look immaculate. Saving sprite coordinates in pixels instead of UVs is flawed because it means you cant upload different texture mip levels (whether they be generated online or offline) for lesser devices without having to recalculate everything.

In mobile development this is a massive, massive flaw. I have written texture packers before for a couple of different companies, and its not a difficult task at all, so I'm not sure why you are so resistant to it.

If you are point blank not going to do it for whatever reason, could you at least point me in the right direction to modify the NGUI source code so that it does what we want?
Title: Re: Sprite Atlas Broken on IOS (Fixed)
Post by: ArenMook on October 07, 2014, 10:25:48 AM
Pixels are easier to work with. Pixels make sense. People understand pixels. Professionals also understand texture coordinates, sure -- but when the inspector shows values like 0.194663 and 0.846426, what does that tell the average user other than bring confusion?

When the user wants to specify a 4 pixel border around the sprite... should he do it in pixels, or in texture coordinates? If in texcoords, how do you translate 4 pixels into texture coordinate equivalent? Bust out a calculator? If in pixels -- why pixels now? Where to draw the line between using pixels and texture coordinates? How will the two intermix? What if you want to scale the atlas texture, and now all the values you specified in pixels get fubared? You may say "just do conversion on the fly and store texcoords under the hood!". Well, guess what Unity themselves use when you pack textures? Also pixels.

Furthermore, typical GUI textures are rarely dividable by two, or have dimensions that make sense. 17x21 sprites? Certainly. If you think you can simply take a texture and reduce its size to half, consider what will happen to your 17x21 sprites that will suddenly get dimensions of 8.5x10.5 in pixels. Does that make sense in any form anymore?

As I mentioned earlier in the thread, if you want to take your atlas and downscale it, and you are absolutely certain that you won't run into any issues I mentioned above, then go ahead and do just that. Write an editor script that will take the atlas, loop through its array of sprites then automatically convert their coordinates using whatever math you desire. You can then apply the same logic to the texture itself (such as reducing it down to half size), and everything will work without having to touch any NGUI's code.