Author Topic: How can I change the depth order to be set by the z position?  (Read 15036 times)

Sahkan

  • Jr. Member
  • **
  • Thank You
  • -Given: 9
  • -Receive: 0
  • Posts: 74
    • View Profile
How can I change the depth order to be set by the z position?
« on: December 27, 2015, 06:08:36 AM »
I know in older versions on NGUI I had the option to choose between UI and Position.
I'm using the 3.9.6c version right now.
Is there a way to set it now?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: How can I change the depth order to be set by the z position?
« Reply #1 on: December 27, 2015, 05:05:28 PM »
NGUI hasn't worked like that in many years now..

Sahkan

  • Jr. Member
  • **
  • Thank You
  • -Given: 9
  • -Receive: 0
  • Posts: 74
    • View Profile
Re: How can I change the depth order to be set by the z position?
« Reply #2 on: December 28, 2015, 12:55:17 AM »
NGUI hasn't worked like that in many years now..

I see. What would you suggest to do when I want to make a card game like hearthstone that has 3d elements that overlap each other?
Also, I'v noticed the perspective view is not right duo to the scale of the UIRoot component.
Will I have to use an other camera for 3d perspective objects?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: How can I change the depth order to be set by the z position?
« Reply #3 on: December 30, 2015, 02:46:36 AM »
Each card would be on its own panel. Adjust the depth of the panel as needed to bring things in front / behind. You can even write a script that will automatically set the panel depth in its Update() function based on the Z position.

UIRoot is not needed for 3D cameras at all. Even if you do use it, keep it as Constrained.

Shifty Geezer

  • Full Member
  • ***
  • Thank You
  • -Given: 7
  • -Receive: 9
  • Posts: 226
    • View Profile
Re: How can I change the depth order to be set by the z position?
« Reply #4 on: January 03, 2016, 03:43:18 PM »
Why put the cards each in their own panel? Why not just use UISprites and set depth?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: How can I change the depth order to be set by the z position?
« Reply #5 on: January 05, 2016, 06:52:07 AM »
Changing the panel's depth automatically affects all children. Changing a sprite's depth does not.

Sahkan

  • Jr. Member
  • **
  • Thank You
  • -Given: 9
  • -Receive: 0
  • Posts: 74
    • View Profile
Re: How can I change the depth order to be set by the z position?
« Reply #6 on: March 13, 2016, 06:55:44 AM »
Each card would be on its own panel. Adjust the depth of the panel as needed to bring things in front / behind. You can even write a script that will automatically set the panel depth in its Update() function based on the Z position.

UIRoot is not needed for 3D cameras at all. Even if you do use it, keep it as Constrained.

Isn't making an update function that will do it for every object will give a performances hit?
This is a workaround an not an actual solution...
Also I need a real solution for sprites that rotates too so using the z position will not suffice.
Isn't there any line in the ngui scripts somewhere where I can just cancel this behavior and then the objects will just use their z position like all the others?
« Last Edit: March 13, 2016, 07:33:16 AM by Sahkan »

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: How can I change the depth order to be set by the z position?
« Reply #7 on: March 13, 2016, 11:41:26 AM »
No, there isn't. Panels sort widgets based on depth. UICamera sorts panels based on depth. Unity sorts cameras based on depth. Always depth, never Z.

StephenZepp

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 7
    • View Profile
Re: How can I change the depth order to be set by the z position?
« Reply #8 on: March 16, 2016, 05:13:51 PM »
/rant on

I realize that the system is what it is, but I'll be frank--not having control over rendering order at run time is making procedural UI's a nightmare.

This type of scenario routinely happens:

A complex UI is drawn up in a scene using the editor. Being state based (based on user input), multiple panels must be used to allow the depth based auto-sorting to work properly. You spend hours getting all the panels set up, and the various widgets positioned and depth set via "push to back/push to front" so that they render as desired.

You decide to add one small new area to a UI Section, and now NGUI kicks in and decides to re-order the depth of all of your widgets, and UI elements that used to render exactly as you wanted them are now rendering behind other elements (even in the same pane) because the manual depths have been changed somehow.

Ok, so you go back in and re-order the depths appropriately, tediously using "bring to front" on each as needed so that they render properly again....save scene, start scene--and NGUI re-orders depths again.

I love NGUI--it's pretty amazing what you can do, and you've put a hell of a lot of work into it...but having a UI engine that constantly changes the rendering order of your UI based on some algorithm that we can't control directly is extremely difficult to work with.

/rant off, going back to try to get a UI that has been working for weeks to stop rendering my background in front of the rest of the UI no matter what I do.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: How can I change the depth order to be set by the z position?
« Reply #9 on: March 17, 2016, 07:00:13 AM »
NGUI will never reorder anything for you without you doing it yourself. You can adjust depth of widgets and panels using +1 and -1 depth adjustment buttons or by typing the depth value yourself. Doing so doesn't affect other widgets or panels. You can have all of them using the same depth if you like, it will just be unclear what's on top of what. In fact in most cases you won't care unless you specifically want to make sure something is in front or behind, which is the only case you will manually adjust depths of something. Once set, you can duplicate whatever group of widgets you've set up, repeatedly cloning them without any issues. As long as they don't overlap, you won't need to worry about anything.

Bring to front / push to back will indeed change the depth of other widgets, but personally, as an NGUI user, I haven't had to use that feature since I added it many years ago.

StephenZepp

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 7
    • View Profile
Re: How can I change the depth order to be set by the z position?
« Reply #10 on: March 17, 2016, 12:21:01 PM »
NGUI will never reorder anything for you without you doing it yourself. You can adjust depth of widgets and panels using +1 and -1 depth adjustment buttons or by typing the depth value yourself. Doing so doesn't affect other widgets or panels. You can have all of them using the same depth if you like, it will just be unclear what's on top of what. In fact in most cases you won't care unless you specifically want to make sure something is in front or behind, which is the only case you will manually adjust depths of something. Once set, you can duplicate whatever group of widgets you've set up, repeatedly cloning them without any issues. As long as they don't overlap, you won't need to worry about anything.

Bring to front / push to back will indeed change the depth of other widgets, but personally, as an NGUI user, I haven't had to use that feature since I added it many years ago.

I have an object (the map) right now that is saved at depth 1, and on it's own panel (no other objects in the panel). I have an object prefab (the city marker) that gets instantiated at run time for each city location on the map, with the following layers:

CityMarkerBase (widget, depth 1)
--BackSplash (Widget + Sprite, depth 2)
--Shield (Widget + Sprite, depth 3)
--Blazon (Widget + Sprite, depth 4)
--CityName (Widget + UILabel, depth 7)  <-- that's supposed to be 5, but it won't ever save as that--keeps updating itself.

In the map object's Start function, I call  PushBack:       
  1.     void Start () {
  2.         DontDestroyOnLoad(transform.gameObject);
  3.         if (mSelectedCityHelper == null)
  4.           mSelectedCityHelper = GameObject.Find("SelectedCityHelper");
  5.         processCityMarkers();
  6.         NGUITools.PushBack(gameObject);
  7.         }
  8.  

Every item that I procedurally generate I use AddChild to a different pane, I call NGUITools.BringForward to make sure it stays in front of the map object. Even so, every single one of them has the same depth value as the prefab I clone, indicating that BringForward doesn't appear to be doing what it says it should (shouldn't they be at constantly higher depth levels if BringForward makes them render in front of other objects?)

  1.         // set shield
  2.         Transform backsplashT = transform.FindChild("BackSplash");
  3.         NGUITools.BringForward(backsplashT.gameObject);
  4.         // string spriteName = mShieldClass + "_" + mShieldTexture;
  5.         Transform shieldT = transform.FindChild("Shield");
  6.         shieldT.GetComponent<UISprite>().spriteName = mShieldTexture;
  7.         shieldT.GetComponent<UIWidget>().color = mShieldColor;
  8.         NGUITools.BringForward(shieldT.gameObject);
  9.         Transform blazonT = transform.FindChild("Blazon");
  10.         NGUITools.BringForward(blazonT.gameObject);
  11.         blazonT.GetComponent<UISprite>().spriteName = mBlazonTexture;
  12.         blazonT.GetComponent<UIWidget>().color = mBlazonColor;
  13.  

When I run the scene and inspect the map object, it's depth level is 5. Before I put the markers in their own pane, this would slice my layered markers in half, with most of the layered object behind the map (sometimes the name, or the blazon renders above the map, but mostly not).

In summary, the map object, saved at depth 1, gives itself a depth of 5 even after using NGUITools.PushBack after the city markers are generated.

The marker objects all maintain the depths of the prefab, even after each and every layer of the object is modified by NGUITools.BringForward after it is generated.

Not sure what else to add that may help, but something, somewhere isn't working as intended--either I'm doing it wrong, or it is :)

Any thoughts?

StephenZepp

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 7
    • View Profile
Re: How can I change the depth order to be set by the z position?
« Reply #11 on: March 19, 2016, 02:54:09 AM »
I've narrowed this down to only happening when there are scene changes, but also have a 100% reproduction case with what should be a simple inspector popup.

In my game, I have several server synchronization scenes that handle initial "server up" testing, sign up/sign in, data synch from server to client, and then finally switch to my main "Overland" scene.

All scenes are loaded via a GameManager singleton that (should be) is unrelated to the final scene in question.

The final scene in question is loaded with the following (as are all other interstitial scenes):
  1.     public void mapView()
  2.     {
  3.           SceneManager.LoadScene("Overland", LoadSceneMode.Single);
  4.  
  5.     }
  6.  

I've attached several screen shots from the editor inspector that demonstrate widget depth values are conclusively being changed by *something* when the Overland scene loads.

This particular popup panel is a hireling inspector, and has several fields and images that are populated at run time based on what was clicked. Standard stuff, really shouldn't be magical. I've selected images taken from the Editor during scene setup (not running), and then a subset of those images when I run through my startup sequence. The runtime startup sequence begins with the "Startup.Unity" scene, steps through 3 interstitial scenes, then loads Overland.unity scene:

Editor UI Image.png : Display of what the UI should look like (in Editor version, spacing text used)
PopupPanel.png : Display of the Panel used for this UI.
HirelingInspectPane.png : Inspector view of the Widget holding the rest of the UI elements.
Background Texture.png : Simple texture to use as background for the popup. Note Depth is 1
HirelingPortrait.png : top level of a multi-sprite layered display (although not broken in this example, it has been in other instantiations of the bug)
Label (2).png : Inspector view of the Label in question, showing a pre-run depth of 9.

The next set of images are what happens after I select my Startup scene in the Editor, and then hit the Play button:

Editor UI Image -- Label (2) not rendered.png : shows the missing Label.
Hireling Inspector Pane depth now 23.png : shows the same pane as the earlier image, but with the depth changed to 23
Background Texture depth now 24.png : also demonstrates changed depth value of the background texture.
Label (2) depth now 12.png -- shows why the label (2) is not rendering--it's now set to a depth of 12, well behind the background texture.
« Last Edit: March 19, 2016, 03:10:57 AM by StephenZepp »

StephenZepp

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 7
    • View Profile
Re: How can I change the depth order to be set by the z position?
« Reply #12 on: March 19, 2016, 04:40:18 PM »
I literally just watched the depth of a background object jump by 20 simply by clicking on one of it's child objects.

In this case, I have a ScrollView that I populate in run time based on current visitors in a city.

Since I want the user to be able to click on the generated object (to bring up the inspector window described above), I set the widget with the UIScrollView script to a depth of zero, and the widget added to the Grid widget (which is a child of the ScrollView, and a sibling to the UIScrollView) has a depth of zero, with the clickable child widget at a depth of 2.

Everything works fine, I can click the Visitor's icon, and the popup window described in the previous post displays (with the depth issues I've already described)...but the depth of my UIScrollView Widget, AND the depths of my two clickable widgets ON the ScrollView now change to 44.

Ok, fine. Now I click on a second (different) clickable item in the scroll view--and it's depth suddenly becomes 41...and the UIScrollView widget now has a depth of 40.

Since the depths line up at this point, the clickables are all still clickable, and the inspector panel updates appropriately. Close it, move on.

Move to a different city, click on the UI elements that make the scroll view populated again...the depth is still 40 from before, but my new clickable icons are populated with their original values (from the prefab), which put the clickable portion of the icon back at depth 2....but my widget with the UIScrollView is still at depth 40 from the last iteration--therefore these new icons are not clickable.

StephenZepp

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 7
    • View Profile
Re: How can I change the depth order to be set by the z position?
« Reply #13 on: March 20, 2016, 12:31:03 PM »
I've finally been able to track this down, and wanted to provide a response/set of suggestions to future users building highly complex/run-time dynamic UI's. Sorry for the length of this (and previous) posts, but I'm hoping to save others the dozens of hours of learning struggle I went through  ;D

Advice to future users having issues with conflicting depths:
--Follow ArenMook's advice and *always* use Panels to control what is on top of what.
--Never try to manually adjust sorting order via scripted calls to NGUITools BringForward/PushBack/AdjustDepth.
--Try to void using the Selection tools that bring forward/push back as well, as I've personally seen at least one case where it caused me issues.

Please note that my explanation may not be 100% perfect, as I only spent enough time backtracing code to find a fix for my situation, not to fully understand exactly what NGUI is doing when (I want to make my game, not become a PHD in NGUI-ology!).

The long and short of it is that Arenmook is right: NGUI does not, on it's own, muck with depth values, but there is a big caveat: as far as I can tell, any use of the NGUITools calls that can affect depth for any widget can/will affect many other widgets along the way. Specially, NGUITools BringForward, PushBack, and AdjustDepth all have the possibility of affecting other widget's depths, either through the calls to NormalizeXXXDepths, or directly (in the case of AdjustDepth).

In my case, I started off not being aware of the proper use of panels, so everything in my scene had the opportunity to overlap. I used old school techniques of manually drawing up a UI design (on paper) with fixed depths to control draw order (which in and of itself isn't that much of an issue), but failed to account for run time generated UI elements that were copied from prefabs, and therefore kept the depth values of the prefab.

To fix the inevitable issues with depth order conflicts, I started using NGUITools to bring forward/push back, and in some cases directly with adjust depth, but they really can't solve the issue due to how the "NGUI way" expects panels (which is good, don't get me wrong).

I realized I couldn't do it that way, so moved to using Panels, but never took my old NGUITools manual adjustment calls out of the code. My panels solved most of my problems, but ones like I describe in previous posts here would still crop up as those NGUITools calls got hit, and somehow affecting UI Elements that appeared completely unrelated.

After completely removing every single NGUITools call related to depth, all of my UI's started working perfectly under the panel structure.

Just this morning, I used the Editor's "Bring Forward" on one small close button that I needed to move (and couldn't grab with the selection tool), so I brought it forward with the Selection menu--and broke 3 other widgets depth control in the process. Undoing the Selection/Bring Forward in the editor fixed the broken widgets, leading me to conclude I should never use those tools (and ArenMook commented above that he doesn't use them himself if I understood it correctly).