Tasharen Entertainment Forum

Support => NGUI 3 Support => Topic started by: Ferazel on November 01, 2012, 06:35:41 PM

Title: NGUITools.SetActive() & Unity4
Post by: Ferazel on November 01, 2012, 06:35:41 PM
Hi,

I have an implementation question. As everyone should know, in Unity4 they redid their game object active hierarchy.
Anyways, I'm curious why you are recursively setting all of the transform objects to inactive instead of taking of advantage of Unity4's active hierarchy in the NGUI code base.

So for example currently (v2.2.3) the code for activate is:
  1. static void Activate (Transform t)
  2. {
  3.         SetActiveSelf(t.gameObject, true);
  4.  
  5.         for (int i = 0, imax = t.GetChildCount(); i < imax; ++i)
  6.         {
  7.                 Transform child = t.GetChild(i);
  8.                 Activate(child);
  9.         }
  10. }
  11.  

However, why does it go recursively into the children transforms when they will automatically be set to active = false as long as a parent object is set to false? Is there a reason for this?

What I'm proposing is changing it so that it is the following to make it more "Unity4 friendly".
  1. static void Activate (Transform t)
  2. {
  3.         SetActiveSelf(t.gameObject, true);
  4. #if UNITY_3_5
  5.         for (int i = 0, imax = t.GetChildCount(); i < imax; ++i)
  6.         {
  7.                 Transform child = t.GetChild(i);
  8.                 Activate(child);
  9.         }
  10. #endif
  11. }
  12.  

That way the recursiveness that pre 4.0 needed is still there. I'm just curious from a NGUI perspective why that was chosen if I'm not understanding something either in the Unity4 hierarchy or in the way the it would affect NGUI.

Thanks!
Title: Re: NGUITools & Unity4
Post by: ArenMook on November 02, 2012, 02:41:04 AM
You are talking about setting "active to false" yet the code you pasted sets it to true instead. Which one is it then?

Activation is done this way because Unity activates children before parents, which is wrong. Proper activation is parent before child.
Title: Re: NGUITools & Unity4
Post by: Ferazel on November 02, 2012, 10:12:38 AM
Yeah the code I used was for Activate rather than Deactivate. The question though stands for both activating and deactivating an NGUI widget or panel. The point is that recursively activating or deactivating the objects are no longer required or desirable from a GameObject management perspective in Unity4. At least from what I understand.

My question is more interested if there was an NGUI reason why recursion of active states was still desirable. If we keep the children active and disable just the parent object we don't have to recurse at all.

Title: Re: NGUITools.SetActive() & Unity4
Post by: ArenMook on November 02, 2012, 04:24:12 PM
We actually looked into this SetActive earlier today in Unity. The way it was changed was a bit unexpected. Using NGUITools.SetActive(go, false) sets every single object to disabled, while setting a disabled state of an object in 4.0 simply sets its own state to 'disabled' and all the children remain enabled, but disabled in the hierarchy. So... for NGUI's sake, the way it is right now is actually correct, but going forward it's better to use Unity's functionality for non-NGUI stuff.

Talking to Joachim, in a future version the Unity's active state might get changed to activate parents before children, which will eliminate the need for NGUITools.SetActive to begin with.
Title: Re: NGUITools.SetActive() & Unity4
Post by: Ferazel on November 02, 2012, 07:36:01 PM
I actually LIKE how the GO active hierarchy determines the final active state of the GameObject. It also saves the engine time traversing the GameObject hierarchy when it is dispatching messages and rendering (at least I hope).

I don't think setting a child GameObject to true should activate the parent hierarchy to activate that child. I hope Joachim rethinks that idea. However, that's more of a general Unity concern.

My NGUI concern is the following. When using Unity4 and NGUI objects like a UIPanel with a bunch of child widgets for instance, if toggling the only the panel's active state and keeping the child widgets active will have any adverse side effects with NGUI's notifications and even handling. In my own tests it doesn't appear to have any problems just toggling the active state at the parent UIPanel level (thus saving time recursing through the child transforms) as long as the child elements remain active. I thought I'd ask to make sure. Sounds like there shouldn't be a problem if the widgets are expected to be active before the panel anyways? 
Title: Re: NGUITools.SetActive() & Unity4
Post by: ArenMook on November 03, 2012, 04:48:49 AM
You clearly didn't understand what I was saying.

NGUITools.SetActive was created because SetActiveRecursively was enabling children before enabling parents, so when widgets were activated and tried to find a UIPanel on a parent object, they would fail because GetComponent() doesn't work on a disabled game object. I added SetActive because I needed parents to be active before children (which is the correct behavior if you think about it).

Unity 4's system with gameobject.activeSelf and gameobject.activeInHierarchy is indeed a better approach overall... but -- the problem still remains. When you enable a game object, its children receive OnEnable() first, before their parent.
Title: Re: NGUITools.SetActive() & Unity4
Post by: ArenMook on November 03, 2012, 04:53:21 AM
You can test it yourself easily. Create 3 game objects parented to each other in this hierarchy:

1
-- 2
---- 3

Attach this script to them:
  1. using UnityEngine;
  2.  
  3. public class Test : MonoBehaviour
  4. {
  5.         void OnEnable()
  6.         {
  7.                 Debug.Log(name);
  8.         }
  9. }
Run the game. You will see this in the console log:
  1. 1
  2. 2
  3. 3
Now stop the game. Disable the root game object in inspector. Run the game again, and enable the root object in inspector. You will now see this in the console log:
  1. 3
  2. 2
  3. 1
See the issue?