Tasharen Entertainment Forum

Support => NGUI 3 Documentation => Topic started by: ArenMook on November 20, 2013, 11:44:01 PM

Title: UIRoot
Post by: ArenMook on November 20, 2013, 11:44:01 PM
Overview

UIRoot always lies at the bottom of the NGUI UI hierarchy (or top, depending on how you look at it!)

It's responsible for keeping the scale of the UI somewhat more manageable. Since widget coordinates are generally specified in pixels, a 800 by 400 widget will be 800 by 400 units, which is... quite large. UIRoot shrinks itself by the inverse of the screen's height, thus keeping the widgets small and easier to work with.

(http://www.tasharen.com/ngui/uiroot.jpg)   (http://www.tasharen.com/ngui/hierarchy.jpg)

UIRoot has several scaling styles for you to play with. Flexible style lets your UI always be in pixels, and a 300x200 widget will always take 300 by 200 pixels on the screen. This also means that viewing your UI on a low-res device will make your widgets appear rather large in size, and viewing your UI on a high-res device will make your widgets appear small. On the plus side, with this setting your UI will always remain as crisp as possible.

Constrained is the exact opposite of that. When the UIRoot is set to this setting, your screen will always remain the same size as far as NGUI is concerned, regardless of the actual screen size. This means that if a 300x200 widget takes 25% of your screen with the resolution of 1920x1080, it will still take 25% of the screen when you drop your resolution to 1280x720. If you don't want to worry about how your UI will look at different screen sizes and you don't care much about making it as crisp as possible, choose this setting. Don't forget to set the Content dimensions setting when choosing this option.

You can further refine the constrain by choosing whether the content will Fit on the screen or whether it will Fill the screen (when 'fit' is off). Think of it as your Desktop wallpaper. When you choose the Fit method, the wallpaper will always be fully visible on the screen, where if you go with a Fill method, it will always completely fill the screen while maintaining its aspect ratio. Same idea here. See the attached image (http://www.tasharen.com/ngui/roottypes.jpg) for more information.

ConstrainedOnMobiles setting is a combination of the two. It will behave as if the setting was "Flexible" on desktop builds, and it will act as if the size was "Constrained" when targeting mobile platforms.

If you go with the Flexible option, don't forget to set the Minimum and Maximum Height values. These values are used to keep your virtual screen size within "sane" values. So for example if your UI is set to Pixel Perfect mode, and the Minimum Height is set to 720, then some player tries to run your application with the resolution of 800 by 600, the UI will behave as if the setting was "Constrained" with the Content Height set to 720.

Shrink Portrait UI option is designed to adjust your UI's size when the screen is in Portrait mode. It's similar to a height-based adjustment, but it will take the width into consideration as well.

Pro-Tip

The UIRoot always scales itself by 2 / ScreenHeight, where ScreenHeight is either the actual screen height (in pixel perfect mode), or the manual height that you've specified (in fixed size mode). In doing so, the camera that draws the UI can remain at Orthographic Size of 1.

If you don't need the auto-scaling functionality of the UIRoot, you can get rid of this component altogether.

Class Documentation

http://tasharen.com/ngui/docs/class_u_i_root.html

If you have a question regarding this component or would like me to clarify something, just post a reply here.
Title: Re: UIRoot
Post by: emperor1412 on December 18, 2013, 02:33:06 AM
I suggest to have a scale factor which is used to scale up the gameobject that UIRoot is attached to and to set NGUI camera's size property. For example I am using NGUI anchoring with rage tool, I choose the screen height to be 640, scaling style is FixedSize, and the whole NGUI system is too small compared to unity unit. The transform's scale of UIRoot attached-gameobject is set to 0.002472188 which is very small and Rage tool is messed up with that tiny scale. Thus I modified the code a little bit:

in UIRoot.cs:

public float scale = 1000;

protected virtual void Start ()
   {
      UIOrthoCamera oc = GetComponentInChildren<UIOrthoCamera>();

      if (oc != null)
      {
         Debug.LogWarning("UIRoot should not be active at the same time as UIOrthoCamera. Disabling UIOrthoCamera.", oc);
         Camera cam = oc.gameObject.GetComponent<Camera>();
         oc.enabled = false;
         if (cam != null) cam.orthographicSize = 1f * scale;
      }
      else Update();
   }

void Update ()
   {
#if UNITY_EDITOR
      if (!Application.isPlaying && gameObject.layer != 0)
         UnityEditor.EditorPrefs.SetInt("NGUI Layer", gameObject.layer);
#endif
      if (mTrans != null)
      {
         float calcActiveHeight = activeHeight;

         if (calcActiveHeight > 0f )
         {
            float size = 2f / calcActiveHeight;
            
            Vector3 ls = mTrans.localScale;
   
            if (!(Mathf.Abs(ls.x - size) <= float.Epsilon) ||
               !(Mathf.Abs(ls.y - size) <= float.Epsilon) ||
               !(Mathf.Abs(ls.z - size) <= float.Epsilon))
            {
               mTrans.localScale = new Vector3(size * scale, size * scale, size * scale);
            }
         }
      }
   }

I am not sure if it break the other code as now It work just fine to me. Hope to have this scale factor variable in the next version.
Title: Re: UIRoot
Post by: ArenMook on December 20, 2013, 12:34:23 PM
Don't use UIRoot in your case. You don't need it. Remove it, and set the ortho camera's size yourself.
Title: Re: UIRoot
Post by: thienhaflash on January 07, 2014, 03:36:52 AM
I think UIRoot should not scale the whole thing down by default, It's very weird to have a root GameObject at some 0.0000xx scale. I belive most of other people would like it better to see UIRoot at scale (1,1,1) - It's what we expect for the first time using a GUI library (and 2D Toolkit is using that). Scaling everything down 0.000xxx will make people confuse as they don't understand what is that value about (and they can't change it). Keeping Orthorgraphic size at 1 is not needed, just set it to Screen.height / 2 ... thanks god I found this post after several years using NGUI, I thought that scale can not be change and I even wrote a script / modify UIRoot's script to prevent the changes. I didn't know that NGUI can live without UIRoot as I belive UIRoot should be the root of all UI, and no UI could survive without UIRoot.

thanks, I got to remove all the UIRoot component now  ;D
Title: Re: UIRoot
Post by: sintua on January 14, 2014, 08:39:49 PM
Is there a reason there isn't a width property for Pixel Perfect or FixedSize? The setup works well for keeping everything in line vertically, but completely ignores the horizontal. As a result, shrinking a screen's resolution leaves a big blank part off to the side, or a larger resolution leaves content hanging off the right side of the screen.

A width setting that controls sizingin the same fashion would be very useful.
Title: Re: UIRoot
Post by: ArenMook on January 14, 2014, 10:05:25 PM
That's what anchors are for.

If you just have it be based on width AND height, then you will end up with skewed UIs. Think of how poor the UI will look like if you designed it with a 4:3 aspect ratio, then tried to display it stretched on a 25:9? All your squares and circles will be horribly stretched rectangles and ovals.

You need to use anchors instead. Check the very first example that comes with NGUI, then watch the video on the 3.0.7 anchoring system.
Title: Re: UIRoot
Post by: LaeusPF on February 11, 2014, 12:20:28 PM
I'm experiencing a significant problem where I can't work with NGUI widgets unless they're under a UIRoot. In previous versions, I could just have a UILabel in the world somewhere (on the ground, or attached to some object). Now, as soon as I add one to some prefab, it immediately creates a UIRoot hierarchy with a UICamera, then parents my prefab to the UI structure. I'm unable to remove the UIRoot in any way -- if I try to move my prefab back out of the hierarchy, I get a bunch of exceptions in the editor.

I tracked this down to the CreatePanel call, which eventually forces a CreateUI if there isn't one. As a test, I tried disabling this functionality, but then the widget doesn't render at all. Is there some new way of having free-floating UIWidgets in the scene? Or should I have dozens of mini UIRoots all over my scene if I want to have NGUI elements sprinkled around?
Title: Re: UIRoot
Post by: ArenMook on February 11, 2014, 09:06:16 PM
It doesn't need to be under a UIRoot.

As long as a widget finds a UIPanel on a parent, it's fine. So make sure you have a panel above your widgets.
Title: Re: UIRoot
Post by: Aithoneku on April 09, 2014, 02:51:27 AM
About setting width - I think I understand completely why there is no such thing, but shouldn't be there also a way to setup minimal width? My problem is that what if I change screen so it's width is small while height is big (screen will look like a pillar or something). The screen size would be configured according height, but because there wouldn't be much horizontal space, everything would break even when using anchors. I'm pretty much aware that in that case the enforcing minimal width could make height greater then maximal height (if we would still keep correct aspect ratio - which is IMHO priority number one) - but I think it's better solution then none at all...
Title: Re: UIRoot
Post by: ArenMook on April 09, 2014, 04:22:39 AM
Set "Shrink Portrait UI" on the UIRoot, Aithoneku.
Title: Re: UIRoot
Post by: t_n on June 24, 2014, 12:40:22 AM
I have a hierarchy like the following,

A (UIRoot)
 - B
C (UIRoot)
 - D

When I destroy A, the D is resized (UIWidget size) automatically.
Why does this happen?

I checked anchor target of D, but it suggests that the target is C.

The only way I found to avoid this is separating the two UIRoot placing
on different layers.
Title: Re: UIRoot
Post by: ArenMook on June 24, 2014, 05:03:05 AM
You should be using different layers if you have different UIRoots. Otherwise organize your UI like this:

UIRoot
- B
- D
Title: Re: UIRoot
Post by: t_n on June 24, 2014, 05:46:17 AM
Ok, thank you Aren.
Title: Re: UIRoot
Post by: ArtemKoval on August 28, 2014, 10:45:15 PM
Hi!

This question is more like clarification.

I'm using Constraint option to preserve rations on different resolutions.

So 1st screenshot is from 22'' desktop, second one - from laptop. As we can see latter one is blurry.

So if I want my UI to be as crisp as possible I should forgo Constraint mode and use Flexible mode?

Thanks, Artem.
Title: Re: UIRoot
Post by: ArenMook on August 30, 2014, 09:32:37 AM
Yes. Flexible mode is the only way to always have crisp looking UIs on all devices.
Title: Re: UIRoot
Post by: StridingDragon on September 18, 2014, 06:07:24 PM
I am seriously confused at this point. I haven't done any work with NGUI for some time and just upgraded to 3.7.2, and nothing seems as it used to be, and I'm lost…

When I create a new 2D GUI it creates a UIRoot with an attached camera, which is fine. However, the red rectangle representing the camera view is ridiculously small, using up, only about a quarter of the width of the actual screen/scene. Why is that? Am I missing something?

I am using one fullscreen scene, representing a 2D screen in the game, so nothing is scrolling etc. Ideally, it would be helpful if the UI placement would actually match the backdrop in terms of size and positions. As it stands right now, I have place the UI elements in places that have no actual relationship to the game screen itself, and it is impossible to place them in code, because the object positions follow an entirely different scale than those of the actual game graphics. The way it is currently, is really quite unusable, but I found no way to fix this.

What am I doing wrong? How can I get NGUI to create a user interface that matches the scale and placement of the scene it belongs to, so that it's not entirely disjointed?

Thanks for any suggestions.
Title: Re: UIRoot
Post by: ArenMook on September 19, 2014, 08:54:22 PM
I'm not sure what you mean. Red rectangle? Do you mean the maroon one? That's the bounds of the panel. By default it will match the bounds of the screen, assuming the UI camera is left at its default size of 1, and you didn't get layers wrong. Make sure that all cameras have proper layers set. Your UI camera should only see the UI layer, and your other cameras should not see the UI layer.
Title: Re: UIRoot
Post by: StridingDragon on September 21, 2014, 06:34:28 PM
It's not maroon. It's bright red. Enclosed is a screenshot for you to look at. I've noticed that the red box changes depending on how I adjust the "Game" screen window, but no matter what I do, it never matches up with the actual size of the scene. Keep in mind that my scene is supposed to be a single-screen entity. Think of it as a menu screen that does not scroll or move or anything.

With the current set up it is virtually impossible to place or control UI elements because they have to be placed on positions that have absolutely no relation to the actual scene positions, not to mention that they will all clutter up there in the small rectangle in the center of the screen, obscuring whatever else is supposed to be there in the scene view.

I hope it's a bit clearer now.
Title: Re: UIRoot
Post by: bac9 on September 22, 2014, 08:18:01 AM
I'm a bit confused with the new UI root scaling. I am using a 3D UI in Constrained mode with height set to 1080 and fit option enabled for it.

Despite that setting, I'm actually getting 2629x1478 pixel area (measured by anchoring a sprite to UIRoot object dimensions). Experimenting with UIRoot further, I found it impossible to actually change that 1478px height with any UIRoot configuration - the only thing that changes is UIRoot transform scale and (if I switch the screen from 16:9 to free aspect and and drag the proportions around) pixel area width, but never the height, no matter what I use (Constrained or Flexible, fitted or not, any resolution in any field). What am I missing?

Edit: Aha, I see it depends on the 3D camera Z distance from the origin. That distance is not directly translated to pixel area height, though: you get 1478 vertical pixels from the camera situated at -1536, and that proportion (1.03924221922) is not really ringing any bells to me. I have just checked the default 3D UI prefab, and the camera Z offset is set to 700 there, which translates to pixel area height of 810, which is again completely incorrect (for default UIRoot fit height setting of 720 pixels). The size also depends on FOV of the camera. I'd expect one of those parameters to be directly controlled by UIRoot depending on selected resolution, but nothing actually happens with them no matter what you input into UIRoot.

What's going wrong here?
Title: Re: UIRoot
Post by: ArenMook on September 22, 2014, 10:44:23 AM
Yeah the 3D cameras make it really difficult to draw the outline correctly. I suggest you stick to 2D cameras unless you really have to use a 3D one. If you do use a 3D one, the outline is not likely to be of any help to you.
Title: Re: UIRoot
Post by: bac9 on September 22, 2014, 11:13:49 AM
So, if I understand correctly, there is no way to directly influence the resolution of pixel area through UIRoot when you are using a 3D camera, with scaling options having no effect unless you are using a 2D camera?

It might be a good idea to communicate that in the UIRoot inspector hints then :)
Title: Re: UIRoot
Post by: StridingDragon on September 22, 2014, 06:34:22 PM
Thanks for the thought, ArenMook… I'm not sure I understand, though. What is a 2D camera, or rather how would I create it? I can only find one type of camera in Unity, and in my scene I have the 2D toggle switched on. What am I missing?
Title: Re: UIRoot
Post by: ArenMook on September 23, 2014, 12:47:27 PM
2D camera is a camera set to "Orthographic" mode. 3D camera is it set to "Perspective". By default NGUI always crates a layout with a 2D camera, unless you explicitly choose to create a 3D one via the menu.
Title: Re: UIRoot
Post by: StridingDragon on September 23, 2014, 03:57:53 PM
In that case my main camera is a 2D camera. However, comparing the cameras, I noticed that I had my main camera set to a size of 5, which created the discrepancy. Once I set my NGUI camera to 5 as well, everything is as it should be. Problem solved!  :D

Thanks so much for the help, ArenMook
Title: Re: UIRoot
Post by: PoN on October 29, 2014, 01:08:49 AM
How to change Scaling Style by code ?
Title: Re: UIRoot
Post by: ArenMook on October 29, 2014, 05:37:46 AM
UIRoot.scalingStyle
Title: Re: UIRoot
Post by: PoN on October 30, 2014, 11:36:59 PM
Aren , could you help to me pls, i have a trouble.

If i build for ios with game screen size 1024*768 and run on iphone 5s, moving anchored widgets are displaying not so good (vertical crop), i mean wrong position not same on unity game screen, as if i run this builded app on a ipad 2mini anchored widgets are displaying good (moving to right positions) as i see on unity game screen. Even i set UIRoot manualWidth by code . if i set screen game size in unity to 1136*640 , build and run on iphone 5s everything are looking good, but if run on ipad 2mini that looking not so good (vertical crop). Don't understand this system, bcoz if i change game screen size in unity , always everything are looking good.
Title: Re: UIRoot
Post by: ArenMook on November 01, 2014, 08:11:52 AM
Anchors must be set to update OnUpdate if you are moving them or changing anything at run-time. Also depending on how you move them, if you use tweens it won't work as expected because tweens remember the starting position, which may be prior to anchor update.
Title: Re: UIRoot
Post by: PoN on November 02, 2014, 07:52:19 AM
You're right ArenMook. But if i'll use OnUpdate , it makes unmovable widget objects by tween.now i just hardcoded positions of widget objects depends on platform.

Thanks ArenMook.