Tasharen Entertainment Forum

Support => NGUI 3 Support => Topic started by: iandunlop_oefun on May 15, 2012, 12:24:35 AM

Title: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: iandunlop_oefun on May 15, 2012, 12:24:35 AM
Hi,

First of all I'm new to NGUI so perhaps I'm missing some step. I've reviewed the docs, video and several posts on this issue but none seem to have the issue I have.

I have a button and a group of radio buttons (under the UIRoot / Camera / Anchor / Panel) as well as a couple of labels.

Setup:
- game reference atlas prefab
- font reference prefab
- iPad HD game atlas (and font) prefabs (pixel size set to 1.0)
- iPhone HD game atlas (and font) prefabs (pixel size set to 2.0)
- UIRoot (auto off and set to manual height of 1536)
- UIRoot has a atlas change script, on Awake() it swaps the atlas references to point to the appropriate iPad / iPhone selection (uses the .replacement property as mentioned in other threads)
- UI elements all point to the reference atlas / font
- Note: both the iPad and iPhone atlases use the exact same art / names. There is no change in the actual size. I'm using a different atlas so I can set the pixel size on the atlas. (Perhaps there is a better way to handle this?)

1. I select the 960x640 rez and run the app in the editor.

2. When I run the app, the script correctly switches my atlas and font references over to the iPhone atlas.

3. However when I view the screen, they are the wrong size. They are still accessing the iPad atlas.

4. If I mouse/hover over the button or touch the button it will "pop" to a larger size. I'm assuming this is now displaying the correct sprite from the iPhone atlas. Once the button has refreshed it's forever at the larger size (expected).

5. My radio button group does not exhibit this behavior. They stay at the iPad size.


I was expecting that when viewing at 960x640 all the buttons would appear twice as large. But this does not happen. Does anyone have any ideas?


Cheers,
   Ian Dunlop


Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: Nicki on May 15, 2012, 03:59:04 AM
Is the panel marked as static?
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: loopyllama on May 15, 2012, 10:22:48 AM
At least one problem you have is the UIRoot manual height. It needs to be set to the height of the screen resolution...so on iphone HD it needs to be either 960 or 640, depending on your app being landscape or portrait.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: iandunlop_oefun on May 15, 2012, 11:53:55 AM
Is the panel marked as static?

I assume you're referring to the 'Check if widgets won't move' on the UIPanel - this is unchecked.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: iandunlop_oefun on May 15, 2012, 12:01:26 PM
At least one problem you have is the UIRoot manual height. It needs to be set to the height of the screen resolution...so on iphone HD it needs to be either 960 or 640, depending on your app being landscape or portrait.

My app is landscape. I did experiment setting this to 640 and it does increase the size of the buttons etc. However, I don't see how this would work properly given the pixel size property on the atlas. There is still a refresh issue. When I mouse hover over or touch the button it doubles in size (so it's now approx. x4 larger than the iPad version).
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: loopyllama on May 15, 2012, 01:17:31 PM
Maybe it is a refresh problem, but that can not be certain until all other things are correct. You definitely need to set the manual height to 640 for the iphone. Also your pixel size is wrong. Did you set up your ref atlas using the iPad hd resolution? If so, your pixel size needs to be iPad hd height / 640 for your iPhone hd atlas instead of 2.0
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: iandunlop_oefun on May 15, 2012, 01:39:20 PM
Maybe it is a refresh problem, but that can not be certain until all other things are correct. You definitely need to set the manual height to 640 for the iphone. Also your pixel size is wrong. Did you set up your ref atlas using the iPad hd resolution? If so, your pixel size needs to be iPad hd height / 640 for your iPhone hd atlas instead of 2.0

The app was / is setup as a manual height of 1536 and using the iPad HD atlases (referenced by the main atlas / font reference).

It shouldn't make any difference what I set the pixel size to. It's a multiplier so the view should adjust as needed. For a test I set the manual height and pixel size as you state above. The view initially presents as "double" the size (due to the 1536 / 640). However, I still get the same refresh issue. When I hover / touch the button it expands to x2 the size so I end up with approx. x4 the iPad size.

The manual height settings works as advertised. The switching of the atlases is also working, but the effect doesn't occur for anything. The exception to this case is when I hover or touch the button. Then it "pops" to "double" the size.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: ArenMook on May 15, 2012, 02:07:14 PM
After changing your reference atlas, try this:

NGUITools.Broadcast("MarkAsChanged");
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: ArenMook on May 15, 2012, 02:08:19 PM
Btw, there is a bug in Unity in regards to Awake() execution, my guess is you're running into it here.

Your Awake() function is getting called after OnEnable() of others unless you add an empty OnEnable() function to your script.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: iandunlop_oefun on May 15, 2012, 02:55:42 PM
After changing your reference atlas, try this:

NGUITools.Broadcast("MarkAsChanged");

I tried this. It made no difference - same refresh problem still exists.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: iandunlop_oefun on May 15, 2012, 02:56:59 PM
Btw, there is a bug in Unity in regards to Awake() execution, my guess is you're running into it here.

Your Awake() function is getting called after OnEnable() of others unless you add an empty OnEnable() function to your script.

Interesting - thanks for the tip. However, I tried it and it made no difference. Same refresh issue still exists.

What about the script execution order feature in Unity - is there a particular order that would work here?
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: ArenMook on May 15, 2012, 03:18:53 PM
Your atlas replacement script should run first.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: iandunlop_oefun on May 15, 2012, 03:26:30 PM
Your atlas replacement script should run first.

I set my script to -500 (which is before everything in the script execution order list). The issue still persists.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: ArenMook on May 15, 2012, 03:28:25 PM
One other thing you can try is have your atlas get switched in a different scene (usually the load scene), that will then load your actual scene.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: iandunlop_oefun on May 15, 2012, 03:55:03 PM
One other thing you can try is have your atlas get switched in a different scene (usually the load scene), that will then load your actual scene.

I think I can safely say this problem is not an order of execution issue. I just tried this and it did not fix the issue. It's appears to be an update issue. For some reason the button draws with the iPad atlas and only reflects the replaced (replacement) iPhone atlas when I hover or touch the button.

Can you offer some insight into how the pixel size property is used on startup? (FWIW, my atlases are for iPhone and iPad are identical.)
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: ArenMook on May 15, 2012, 03:58:10 PM
Well, then I am at a loss. Assuming you set the replacement atlas correctly, it should get used when the button is created. Methinks you'll need to debug that a bit more.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: iandunlop_oefun on May 15, 2012, 05:47:36 PM
Well, then I am at a loss. Assuming you set the replacement atlas correctly, it should get used when the button is created. Methinks you'll need to debug that a bit more.

Ok, I think I'm getting closer to the cause of the issue. The button in question appears at the expected size when I hover over it. Looking at the SDK source I couldn't find any direct way that the atlas pixelSize property is used, other than the UISprite.MakePixelPerfect() method. Looking at UIImageButton.OnHover(bool isOver) I can see now why the button "pops" to it's expected size - because that directly calls MakePixelPerfect().

So, unless MakePixelPerfect is called the UISprite won't reflect the atlases pixelSize value. On initialization MakePixelPerfect is not called. This is why on first presentation of the view the button does not reflect the pixelSize multiplier.

Any ideas?

Is there some way to force MakePixelPerfect?
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: iandunlop_oefun on May 15, 2012, 06:46:33 PM
For UIImageButton the fix is fairly straightforward - just call MakePixelPerfect() inside the Start() method. However, I ran into another issue where pixelSize isn't accounted for - the colliders on buttons don't update. So you're left with a small rect that doesn't match the visual size.

Given these issues I've abandoned trying to use the atlas pixelSize. Perhaps there is something I'm doing wrong here but I can't figure it out.

What I'm now doing is switching the manual height setting on the UIRoot and leaving the pixel size on *all* atlases set to 1.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: ArenMook on May 15, 2012, 09:30:06 PM
You're supposed to be working with a manual height to begin with. Pixel size only works with a manually set height. You basically choose the target height you'll be designing your UI in, then stick with it, and if the resolution is high enough, swap to an HD atlas.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: ArenMook on May 15, 2012, 09:32:30 PM
Oh and btw you can call MakePixelPerfect on everything by broadcasting it:

  1. NGUITools.Broadcast("MakePixelPerfect");
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: ArenMook on May 15, 2012, 09:34:38 PM
Another note... colliders on buttons shouldn't update. There is no reason for them to update. As far as they're concerned, the UI size hasn't changed because the scale of UIRoot shouldn't be changing (this is where the "automatic" being turned off comes in).

They will only scale if you've turned the automatic back on for some reason, which doesn't mix with the pixelSize setting.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: iandunlop_oefun on May 15, 2012, 10:07:15 PM
You're supposed to be working with a manual height to begin with. Pixel size only works with a manually set height. You basically choose the target height you'll be designing your UI in, then stick with it, and if the resolution is high enough, swap to an HD atlas.

I am - see my original post. My point was that I'm now dynamically switching the manual height based on the device / destination screen size.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: iandunlop_oefun on May 15, 2012, 10:08:16 PM
Oh and btw you can call MakePixelPerfect on everything by broadcasting it:

  1. NGUITools.Broadcast("MakePixelPerfect");

That would solve one particular issue but doesn't address the collider problem.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: iandunlop_oefun on May 15, 2012, 10:20:45 PM
Another note... colliders on buttons shouldn't update. There is no reason for them to update. As far as they're concerned, the UI size hasn't changed because the scale of UIRoot shouldn't be changing (this is where the "automatic" being turned off comes in).

They will only scale if you've turned the automatic back on for some reason, which doesn't mix with the pixelSize setting.

Manual height was being set (automatic was not enabled on the UIRoot).

Atlas.pixelSize is not being handled correctly on UIImageButton's. Hence the "pop" I was getting when I hovered over or touched the button. In your code you only use pixelSize in the MakePixelPerfect method.

The collider's do need to increase in size because the size of the button on screen is larger. In my test case I was switching to an iPhone atlas with atlas pixelSize set to 2. However, the collider was still set for the original iPad version of the button.

My solution was to set *all* my atlases to 1 and change the manual height dynamically based on device screen size.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: ArenMook on May 15, 2012, 11:02:54 PM
The collider on the screen shouldn't change. You may have a bigger screen size, but since you are not using it (you're using the manual setting on the root), it is completely irrelevant. The button should stay the same size proportionally. Does your button's size change? If your button is 200x30, it should still be 200x30 after the atlas swap. The whole point of the atlas swapping is to handle doubling (or halving) of resolutions, iOS style.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: loopyllama on May 15, 2012, 11:27:21 PM
My curiosity has to the better of me. You mention you use the same art for both atlases. Is your art designed to be pixel perfect for the iPhone 4 or the iPad 3? Which one? Then I cannot help but ask why you are not using different art when you are not keeping pixels 1:1 (which would be setting the UIRoot to automatic). Are you SURE you shouldn't be disabling your atlas switching code, using your single iPad 3 atlas set to pixel size of 1, and setting the UIRoot to automatic? It really sounds like that is what you want. That would make a button that is 100 pixels tall stay 100 pixels tall on any device. For instance in the wacky case of a button that is 500 pixels tall, it would be almost 1/3 of the screen tall on the ipad3 and over half the screen tall on the iPhone 4. It sounds like you want to want to take the pixel perfect button on the iPhone 4 that would be over half the screen and make it twice as big. But instead you are trying to make pixel perfect art two times bigger when switching from the iPad 3 to iPhone 4? I must have misread something. Please set the record straight to make helping easier.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: iandunlop_oefun on May 15, 2012, 11:38:42 PM
The collider on the screen shouldn't change. You may have a bigger screen size, but since you are not using it (you're using the manual setting on the root), it is completely irrelevant. The button should stay the same size proportionally. Does your button's size change? If your button is 200x30, it should still be 200x30 after the atlas swap. The whole point of the atlas swapping is to handle doubling (or halving) of resolutions, iOS style.

I have a smaller screen size. I'm going from iPad retina to iPhone retina. The pixelSize on the iPad atlas was 1 and the pixelSize on the iPhone atlas was 2. The button grows in size when running at 960x640 (if I touch the button or hover over it). In all cases manual height on the UIRoot was set to 1536.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: ArenMook on May 15, 2012, 11:40:48 PM
So your problem is that you're mixing two incompatible screen sizes -- iPhone and iPad. iPhone's resolution isn't simply half of iPad's. iPhone is 960x640, while iPad3 is 2048x1536. 1536/2=768, not 640.

Edit: Edited because I should be using height, not width. <_<
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: ArenMook on May 15, 2012, 11:41:56 PM
Your pixel size for your iPhone atlas should be 1536/640=2.4
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: iandunlop_oefun on May 15, 2012, 11:50:48 PM
My curiosity has to the better of me. You mention you use the same art for both atlases. Is your art designed to be pixel perfect for the iPhone 4 or the iPad 3? Which one? Then I cannot help but ask why you are not using different art when you are not keeping pixels 1:1 (which would be setting the UIRoot to automatic). Are you SURE you shouldn't be disabling your atlas switching code, using your single iPad 3 atlas set to pixel size of 1, and setting the UIRoot to automatic? It really sounds like that is what you want. That would make a button that is 100 pixels tall stay 100 pixels tall on any device. For instance in the wacky case of a button that is 500 pixels tall, it would be almost 1/3 of the screen tall on the ipad3 and over half the screen tall on the iPhone 4. It sounds like you want to want to take the pixel perfect button on the iPhone 4 that would be over half the screen and make it twice as big. But instead you are trying to make pixel perfect art two times bigger when switching from the iPad 3 to iPhone 4? I must have misread something. Please set the record straight to make helping easier.

Art is designed for iPad retina (iPad 3). For iPhone retina I want the buttons to be larger on screen (because the physical display is smaller).

These are approx. sizes:
- If I have an 80x80 iPad retina button, I want that to be 80x80 on iPhone retina.
- However, on iPhone (non-retina) I need that button to be 40x40

I will investigate UIRoot in automatic mode - perhaps I should be using that?
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: iandunlop_oefun on May 15, 2012, 11:52:46 PM
Your pixel size for your iPhone atlas should be 1536/640=2.4

Sure - fair enough. However, that isn't the problem. That won't address the problem with atlas pixelSize being used inconsistently in the SDK / source.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: ArenMook on May 16, 2012, 12:03:11 AM
How is that? UIImageButton is not even a widget. It's just a script that uses sprites. And sprites use the pixel size property just fine.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: iandunlop_oefun on May 16, 2012, 12:07:11 AM
How is that? UIImageButton is not even a widget. It's just a script that uses sprites. And sprites use the pixel size property just fine.

I explained that in an earlier post. MakePixelPerfect is called in the OnHover, but not on the Start() method of UIImageButton. That difference causes the button to appear larger when I hover over it.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: ArenMook on May 16, 2012, 12:08:40 AM
Correct, and as I mentioned the size of the button shouldn't change. Ever. That's what the pixel size is supposed to address. You use the same size on screen, while doubling (or halving) your atlas size. In your case you were not setting the proper pixel size, so your button size was physically changing when you hovered over it -- something that should not happen.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: ArenMook on May 16, 2012, 12:09:58 AM
Just to clarify, the point of pixel size is this: MakePixelPerfect before the atlas change should look exactly the same size as MakePixelPerfect after the atlas change.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: iandunlop_oefun on May 16, 2012, 12:18:41 AM
Correct, and as I mentioned the size of the button shouldn't change. Ever. That's what the pixel size is supposed to address. You use the same size on screen, while doubling (or halving) your atlas size. In your case you were not setting the proper pixel size, so your button size was physically changing when you hovered over it -- something that should not happen.

If I set the atlas pixelSize to 2.4, the button becomes even larger when I hover over it. I think I understand that you are saying you can't use atlases that are the same size. i.e. I have to make my iPhone atlas smaller. My point is that if pixelSize was handled correctly throughout the code then it would solve my original problem. Which I understand may be beyond the scope of the feature originally.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: loopyllama on May 16, 2012, 12:23:10 AM
@ian
if you have a source art that is 80 pixels tall on the ipad 3 with a height of 1536, it takes up this percent of the screen:
80 / 1536 = 0.052 percent of the screen

if you used this same art on the iphone 4 that has a screen height of 640, it takes up this percent of the screen:
80 / 640 = 0.125 percent of the screen

this means if you use your ipad 3 art on the iphone 4 and set NGUI UIRoot to automatic, the art will take up more than double the screen space on the iphone 4, than when compared to the ipad 3. Set it to automatic!

(you do not want to do what you are trying to do, but if you reaaaaaally want to see it try setting your reference atlas replacement to None in the inspector. Then your script sets your atlas to whatever you want on detection)

@ArenMook
Earlier in your postings you mention to someone not to do something like this in a switch atlas script:
public UIAtlas refAtlas;
public UIAtlas iphoneHDAtlas;
public UIAtlas ipadHDAtlas;
and you suggest to do a Resources.Load because the above way will load all the atlases into memory. I think those are variables are just references/pointers to the file and assigning one does nothing more than point to the resource/prefab. In either case wouldn't you always want to set your replacement property in your atlas to null before shipping your app? I think the whole "atlas switching" is really a misnomer-- it is more of a "atlas setting" because the whole switching part of it really only happens with the developer sitting on his computer switching between atlases...meaning technically ian would never really encounter the switching issue because he should really be switching from null to his detected atlas...
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: iandunlop_oefun on May 16, 2012, 12:26:02 AM
Just to clarify, the point of pixel size is this: MakePixelPerfect before the atlas change should look exactly the same size as MakePixelPerfect after the atlas change.

Ok, but it won't in the case I ran into. Which is related to using the same size of sprites for both atlases, and making the iPhone atlas use a pixel size of 2.0. Perhaps the SDK could warn in the log when trying to do that? It just wasn't clear to me that you couldn't use it like this.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: ArenMook on May 16, 2012, 01:32:09 AM
@loopyllama: Well, yes -- you can call it "setting" instead. I'm pretty sure referencing the atlas as a public property will result in it being loaded into memory when you load the level, so if you have both specified, both will be in memory, which is obviously something you don't want. Resources.Load simply ensures that they are loaded only when you need them. And yes, you will want to set the reference to null before doing a build.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: loopyllama on May 16, 2012, 02:11:21 AM
@ArenMook
Thanks for clearing up the null reference atlas part.
I am pretty sure that a public member variable set to a prefab is a hint for unity to include that prefab in the build. I believe this does not consume significant memory. I believe Resouces.Load is equal to calling Instantiate on the public member variable. I hope I am right!

Edit: I am not totally correct. Use the Resources.Load method where performance matters!
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: Nicki on May 16, 2012, 02:34:21 AM
Anything in the Resources folder is included in the build, but not loaded until you load it specifically.

If you want something to use an SD atlas for low res iphone, HD atlas for iphone retina and ipad, while keeping everything pixel perfect (smaller on iphone retina than ipad) then make a little script that sets the UIRoot manual height different on the ipad. If SD atlas has a pixel size of 1 and HD has a pixel size of 0.5f, you set your root manual height to half the height of the highres device - that is, the same as SD iphone for HD iphone, and actual resolution height /2 for ipad (either 384 or 512).
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: Nicki on May 16, 2012, 02:42:21 AM
Loopy: You are wrong. Stuff referenced in a public member is loaded into memory when a scene is loaded. The prefab will consume as much resources as its assets demand. You can reference it by name (as a string) and load it via Resources.Load, then it will only take up memory when you actually instantiate it.

Instantiating a public variable, will make a clone of that object, consuming 2x memory (original + clone), I believe.
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: loopyllama on May 16, 2012, 03:52:13 AM
Nicki: partially, it gets loaded into RAM but not VRAM as ArenMook says.
On a mobile device this would be bad, so member variables is not the way to go...
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: ArenMook on May 16, 2012, 03:53:08 AM
You're both right, actually. The texture is in memory -- RAM, not video memory. :)
Title: Re: Universal SD / HD Switching for iOS (iPad / iPhone) - Refresh problem
Post by: loopyllama on May 16, 2012, 04:22:49 AM
ok, ok! You are right ArenMook. It gets loaded into RAM with the reference. It gets loaded into VRAM when the object is instantiated.