Author Topic: Understanding BoxCollider Depth  (Read 9104 times)

Tiktaalik

  • Newbie
  • *
  • Thank You
  • -Given: 7
  • -Receive: 0
  • Posts: 39
    • View Profile
Understanding BoxCollider Depth
« on: October 03, 2013, 01:33:46 PM »
I have an issue where I have a panel with two buttons on it and I'm getting really inconsistent button selection ability.

From my understanding the Z Depth of the BoxCollider should be increasingly negative for objects that are "on top" and clickable. I'm running into issues where even when I force edit the Z of the BoxCollider of the buttons to be more negative than the panel behind the buttons, when I run the game these button boxCollider values are somehow overridden to some other (less negative) value and the buttons remain unclickable. I'm at the point where I don't know how to proceed because I don't understand what sort of things are happening behind the scenes and how this system is supposed to work.

How can I fix this?
What actions may inadvertently "break" the default BoxCollider setup and how does one fix it?
What is the best workflow for creating panels and buttons and having BoxCollider depth work as expected?
Am I correct in believing that widget depth has absolutely nothing to do with BoxCollider depth?

For reference my hierarchy looks like:

UIPanel (has boxCollider)
-->View (background sprite)
-->--> Button (has boxCollider)
-->--> Button (has boxCollider)

Running 3.0.1

Tiktaalik

  • Newbie
  • *
  • Thank You
  • -Given: 7
  • -Receive: 0
  • Posts: 39
    • View Profile
Re: Understanding BoxCollider Depth
« Reply #1 on: October 03, 2013, 03:34:07 PM »
I'm still interested in learning a bit more about the BoxColliders with regard to depth and best practices but fortunately for the immediate moment I've solved my issue where it seemed like my manual edits to BoxCollider Z was being stomped. There was a component attached to the objects which inherited from UIWidget but did not concern itself with dimensions and so since its width and height were zero it fell into this area of code in UIWidget...

  1. protected virtual void OnEnable ()
  2.         {
  3.                 list.Add(this);
  4.                 mChanged = true;
  5.                 mPanel = null;
  6.  
  7.                 // Prior to NGUI 2.7.0 width and height was specified as transform's local scale
  8.                 if (mWidth == 0 && mHeight == 0)
  9.                 {
  10.                         UpgradeFrom265(); <--- calls NGUITools.AddWidgetCollider(gameObject, true);
  11.                         ...
  12.  


Manually setting the width and height to 1 fixes this issue but I should probably go back and fix this issue of this Component inheriting from a widget. It probably doesn't need to.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Understanding BoxCollider Depth
« Reply #2 on: October 04, 2013, 02:17:53 AM »
3.0.2 completely removes the need to adjust the Z of colliders, so it'll help you here.

Prior to that, simply adjusting the collider via ALT+SHIFT+C generally is enough. If you have two panels in the same place using widgets with the same depth that have colliders on them, then there may be conflicts, however.

Enable "debug" on the UICamera to see what the mouse is hovering over.

Tiktaalik

  • Newbie
  • *
  • Thank You
  • -Given: 7
  • -Receive: 0
  • Posts: 39
    • View Profile
Re: Understanding BoxCollider Depth
« Reply #3 on: October 08, 2013, 12:24:27 PM »
Alright I upgraded to 3.0.2 but while I'm pleased that everything has been simplified to go off depth only, I'm still having some depth issues when having panels overlap other panels, and I haven't been able to figure out what is going on.

I wanted to have a panel go on top of another and so I thought perhaps I should call NGUITools.BringForward() on the gameObject. I see that the depths of all the widgets are increased by 1000 and then normalized, and all the depths appear fine but I'm still having issues where I can select items under the panel, and other depth oddities. For example I have a button with depth 24, but when I hover over it with the mouse, the UICamera debug says I'm hitting my "View" object, which is a UISprite with depth 21. The buttons on the panel below also have lower depth values but I am able to hit them.

I guess I have three questions:

1. If you want to have a panel go on top of another what should one be calling to fixup depths at runtime? Is NGUITools.BringForward() not the right answer?

2. Why am I seeing correct looking depth values but my collision behaviour isn't matching?

3. Is there some special way that I have to design my panel objects to get this to work? I've experimented with a few things but since nothing is working for me as expected I don't know if I'm doing it right. Should UIPanel always be the top parent in a hierarchy of child widgets?

I think a good addition to your documentation could be a "best practices" page that shows ideally how one should be organizing your panels, widgets and anchors and such to get ideal behaviour.

Thanks.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Understanding BoxCollider Depth
« Reply #4 on: October 08, 2013, 12:53:20 PM »
If you want to bring some panel forward, simply increase its depth. No need to call bring forward on the widgets within.

Tiktaalik

  • Newbie
  • *
  • Thank You
  • -Given: 7
  • -Receive: 0
  • Posts: 39
    • View Profile
Re: Understanding BoxCollider Depth
« Reply #5 on: October 08, 2013, 02:27:55 PM »
If you want to bring some panel forward, simply increase its depth. No need to call bring forward on the widgets within.

This fixes my issue of being able to click on the buttons behind the panel, but I'm sorry to say that I still can't click on buttons on the panel.

I call the following in a script attached to the same GameObject that contains a UIPanel script where value is 200.

  1.  UIPanel panel = GetComponent<UIPanel>();
  2.  panel.depth = value;
  3.  

And I see that the UIPanel script depth is now 200, but my buttons remain at the depths I have previously set (I assume this is how it's supposed to work?). When I mouse over the panel's buttons I'm still selecting the "View" which is the next child object to the UIPanel containing a UISprite for the background and a box collider. Its depth is 1. The depth of my button graphics are 3.

Panel (UIPanel)
-->View (UISprite)
-->-->TitleBar (no UIWidgets)
-->-->-->BackButton (UIButton)

Where should I look for problems next?

Tiktaalik

  • Newbie
  • *
  • Thank You
  • -Given: 7
  • -Receive: 0
  • Posts: 39
    • View Profile
Re: Understanding BoxCollider Depth
« Reply #6 on: October 08, 2013, 02:55:38 PM »
Ok I put some print statements in UIWidget.raycastDepth and it looks that for my button UIWidget my "mPanel" variable isn't being set, so that's resulting in a bad depth. I'll keep looking into that area...


from UIWidget.raycastDepth
  1. return (mPanel != null) ? mDepth + mPanel.depth * 1000 : mDepth;
  2.  
Output:
Quote
UIWidget.raycastDepth.Get GO: View , PanelDepth:200, Final Depth: 200001 , mDepth: 1
UIWidget.raycastDepth.Get GO: DismissButton , No Panel? Final Depth: 22 , mDepth: 22

« Last Edit: October 08, 2013, 05:37:09 PM by Tiktaalik »

Tiktaalik

  • Newbie
  • *
  • Thank You
  • -Given: 7
  • -Receive: 0
  • Posts: 39
    • View Profile
Re: Understanding BoxCollider Depth
« Reply #7 on: October 08, 2013, 05:46:22 PM »
Ok I'm pretty sure I figured out the issue.

On the problem panels where there was some UIWidget that seemingly had a null mPanel there existed an additional script which inherited from UIWidget, meaning that there were actually two UIWidgets on the GameObject. Importantly this second object didn't implement several things that were important for UIWidget functionality such as having a valid material, and so various UIWidget code failed.

The problem was highlighted in depth code because the following bit of code just grabs one UIWidget and in this case it was grabbing the malformed one.

  1. static public int CalculateRaycastDepth (GameObject go)
  2.         {
  3.                 UIWidget w = go.GetComponent<UIWidget>();
  4.                 if (w != null) {
  5.                         return w.raycastDepth;
  6.                         ....
  7.  

So I guess the lesson from this is to only have one UIWidget per GameObject, which seems totally reasonable to me.