Author Topic: Where to put UIs and how to reference them  (Read 3879 times)

bbbscarter

  • Guest
Where to put UIs and how to reference them
« on: June 01, 2012, 01:29:11 PM »
Hi, and thanks for NGUI - it's great.

I have a couple of general questions regarding scene layout and workflow, which I was hoping you'd be able help me with. Specifically, I'm wondering what the recommended place is for keeping UI components. Should they be kept as prefabs or inactive instances?

If the recommended way is as instances, how do you reference UI components when it comes to activating them? For example, if clicking a door should bring up the 'open door' UI, how do reference that specific UI in the editor? You can't reference it directly in the door, as the UI elements exist across multiple levels and the door is specific to a single level - similarly it's a problem if you need to refer to a UI from a prefab. Using string names to refer to them? Seems a bit sloppy. Something else I've missed?

If, however, the recommended way is via prefabs, is there anything specific you need to know about instancing them? In particular, I've noticed that if I have a UI panel with a scaling tween that goes from, say, 0.5 to 1 in all dimensions, when instanced the panel spends a single frame at full size in the bottom left hand corner of the screen before snapping into the right scale and position.

Thanks in advance for the help, it's much appreciated!

Simon

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Where to put UIs and how to reference them
« Reply #1 on: June 01, 2012, 01:37:21 PM »
That depends -- are you only going to be using them in one scene? If so, keep them local to that scene. If the UI components are going to be shared, make them be prefabs.

Generally whatever script you have on the door should have a reference to the prefab used for the UI. If there is anything special that needs to change (text, data, etc), modify it after instantiating the prefab.

Use NGUITools.AddChild to instantiate them. Personally in Windward I have a different tool -- HUDRoot, and it has AddChild there as well, so everything added via that method ends up in the UI hierarchy. HUDRoot is accessible via a singleton.

You generally should spawn prefabs off-screen first.

bbbscarter

  • Guest
Re: Where to put UIs and how to reference them
« Reply #2 on: June 02, 2012, 02:40:54 PM »
Thanks for the quick response! That all makes sense, so I'll stick with prefabs (I've got multiple levels, so that makes sense), although now I have a couple of other questions.

Firstly, when instancing a UI prefab, is there a part of the UI hierarchy that should pre-exist for parenting? Cloning everything from a prefab (from UIRoot down) works, but I'm not sure if that's best practise. If not, which part of the UI should come from the prefab, and which parts should pre-exist in the scene (via your singleton suggestion)? I've tried various combinations, and the only one that obviously works is cloning the entire hierarchy; anything else results in panels being in the wrong place (using NGuiTools.AddChild(root, prefab)), and I'm not sure why.

Secondly when you say it's best to instance things off screen and then move them into place, is there an easy or suggested way to do that? And do you need to leave them offscreen for an entire tick, or can you move them immediately after creation?

Thanks again for the help!

Simon

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Where to put UIs and how to reference them
« Reply #3 on: June 02, 2012, 02:45:58 PM »
There should generally be only one UIRoot in the scene. You should ideally re-use as much as possible. For example if you're adding center-anchored components, then chances are you want to make sure that UIAnchor is outside the prefab so you keep re-using it.

As I mentioned, in Windward I have a "HUDRoot" object that's a singleton. When I want to add stuff dynamically, I do NGUITools.AddChild(HUDRoot.instance.gameObject, prefab);

Using Object.Instantiate is not advised. NGUITools.AddChild should fix your single frame issue. I say it's a good idea to instantiate off-screen because this allows you to smoothly animate/tween the panels into view.

bbbscarter

  • Guest
Re: Where to put UIs and how to reference them
« Reply #4 on: June 07, 2012, 07:11:18 AM »
Right, I think I've narrowed down what's going on.

To summarise the problem, when instantiating a gui from a prefab I have a single frame where the ui is in the wrong place. It appears to have something to do with having an anchor which isn't the center.

My repro steps are thus:
- Create a new ui.
- In UIRoot disable Automatic and set the manual height to 640.
- Under the ui panel, create a tileable sprite and set it to something visible, just so you can see something on screen.
- Set the anchor in the ui hierarchy to TopRight.
- Move the panel so it is in the top right of the screen.
- Drag the camera into the project pane to make a prefab of everything bar the UIRoot object and disable/delete the original gameobject.
- Write a script to instantiate and destroy the gui prefab; as you suggested, I'm doing this via a singleton which creates a gameobject with a UIRoot component (also set to automatic=false and manualHeight=640), using a method that does the instantiation via NGUITools.AddChild.
- Run the game and activate/deactivate the gui several times - you should see jumping for one frame. (One thing I noticed is that it doesn't always do it in the editor, but it always does it in the web player and the OSX player. Also it doesn't always do it the first time, but always on subsequent times).

Rerunning the same experiment and setting the anchor to 'center' results in no jumping. FWIW anchors of 'top' and 'bottom' also seem to be fine, anything involving 'left' and 'right' have a single frame jiggle.

Hope this is helpful and that I'm not doing anything stoopid. If it would help for me to send you an example repro case, let me know.

Thanks!

Simon

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Where to put UIs and how to reference them
« Reply #5 on: June 07, 2012, 12:02:28 PM »
The UI will show up where the prefab's position is upon instantiation, unless you use NGUITools.AddChild, which resets that position to 0. Anchor doesn't kick in right away. It's delayed by one frame. This is why I suggested instantiating off-screen.

bbbscarter

  • Guest
Re: Where to put UIs and how to reference them
« Reply #6 on: June 08, 2012, 06:38:02 AM »
Yeah, it's nothing to do with NGuiTools.AddChild, as I'm using that. Seems it's the anchor, which makes sense if, as you say, it's delayed by a frame.

Very happy to instantiate off screen if that's needed to make things work properly, I wasn't clear that was absolutely required. That said, it's a bit fiddly to do as I'm currently just doing quick gui mockups, rather than fancily animated things, so really I just want them to start off where I authored them and stay there.

My bodge solution was to create a 'SingleFrameDisplacement' component script which displaces my gui panel for 1 frame, and then resets its position back to whatever was authored. Seems to get rid of the wibble nicely, but doesn't feel entirely elegant... :)

Thanks!

Simon