Author Topic: Moving prefab into Hierarchy on U5 broken  (Read 7768 times)

arkon3

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 71
    • View Profile
Moving prefab into Hierarchy on U5 broken
« on: March 13, 2015, 07:22:01 PM »
NGUI has a new most annoying bug in U5, If I drag a prefab that contains NGU components into my hierarchy as a child of a UIRoot/Camera it adds a new UIRoot/Camera to the hierarchy and puts the prefab there instead of where I dropped it. Worse it then changes all the layer names in the original UIRoot to the layer name of the prefab I was moving. It also takes that layer name out of the original UIRoot culling mask.

This is different from the last bug I reported as that does this in the other direction (Hierarch to Project)

It's made NGUI almost unusable at the moment, as I often drag prefabs into the UIRoot to edit them or add bits etc before moving them to a resources folder in the project. I reported the bug to Unity also but they passed the buck and said it's NGUI's problem.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Moving prefab into Hierarchy on U5 broken
« Reply #1 on: March 13, 2015, 09:59:44 PM »
I need more details here. When I try it on my end it works as expected.

1. New scene.
2. Open the Prefab Toolbar.
3. Drag any prefab into the scene.
4. Drag more prefabs. Everything works as expected, same UIRoot gets reused.

devomage

  • Sr. Member
  • ****
  • Thank You
  • -Given: 7
  • -Receive: 67
  • Posts: 250
    • View Profile
Re: Moving prefab into Hierarchy on U5 broken
« Reply #2 on: March 14, 2015, 01:58:04 AM »
from what ive been reading - quite a bit of these issues revolve around an existing upgraded project...  rather than a fresh new scene.

arkon3

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 71
    • View Profile
Re: Moving prefab into Hierarchy on U5 broken
« Reply #3 on: March 17, 2015, 06:33:27 AM »
I need more details here. When I try it on my end it works as expected.

1. New scene.
2. Open the Prefab Toolbar.
3. Drag any prefab into the scene.
4. Drag more prefabs. Everything works as expected, same UIRoot gets reused.

This works when you follow what you have just written, but goes wrong if you have more than one panel with different layers.
Try this to see it go wrong:-
1. new scene
2. Create UIRoot with 3d option. (creates a UIRoot with a camera under it)
3. Create 2 panels as children of the camera
4. Create 2 layers with the layer drop down. One called HUD one Called Tower (doesn't matter the names)
5. create 1 prefab with it's layer set to Tower.
6. Drag the prefab into the hierarchy as a child of the Tower Panel.
7. Drag the prefab back out of where you dropped it back to the project window.
8 BANG! it leave another UIRoot in the hierarchy.

edit: I've just been experimenting and it's caused because the Layer UIRoot is on is different from the Layer the panels is on.
BUT this is how you told me to do it to be able to have sprites with different layers. My hierarchy looks like this:-

UIRoot                (Layer set to 0 default)
->Camera           (Layer set to 0 default)
->->PanelTower   (Layer set to 15)
->->->Tower1     (Layer set to 15)
->->PanelHUD     (Layer set to 16)
->->->Button      (Layer set to 16)
->->PanelEnemy  (Layer set to 17)
->->->Enemy1    (Layer set to 17)

« Last Edit: March 17, 2015, 06:39:59 AM by arkon3 »

arkon3

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 71
    • View Profile
Re: Moving prefab into Hierarchy on U5 broken
« Reply #4 on: March 18, 2015, 10:45:44 PM »
Any progress on this? It's so annoying, it practically destroys my hierarchy each time I move a prefab and takes me ages to clean it all back up again.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Moving prefab into Hierarchy on U5 broken
« Reply #5 on: March 19, 2015, 06:47:45 AM »
Open up NGUITools.cs and find the CreateUI function on line 759. Replace it with this:
  1.         /// <summary>
  2.         /// Create a new UI.
  3.         /// </summary>
  4.  
  5.         static public UIPanel CreateUI (Transform trans, bool advanced3D, int layer)
  6.         {
  7.                 // Find the existing UI Root
  8.                 UIRoot root = (trans != null) ? NGUITools.FindInParents<UIRoot>(trans.gameObject) : null;
  9.  
  10.                 if (root == null && UIRoot.list.Count > 0)
  11.                 {
  12.                         foreach (UIRoot r in UIRoot.list)
  13.                         {
  14.                                 if (r.gameObject.layer == layer)
  15.                                 {
  16.                                         root = r;
  17.                                         break;
  18.                                 }
  19.                         }
  20.                 }
  21.  
  22.                 // Try to find an existing panel
  23.                 if (root == null)
  24.                 {
  25.                         for (int i = 0, imax = UIPanel.list.Count; i < imax; ++i)
  26.                         {
  27.                                 UIPanel p = UIPanel.list[i];
  28.                                 GameObject go = p.gameObject;
  29.  
  30.                                 if (go.hideFlags == HideFlags.None && go.layer == layer)
  31.                                 {
  32.                                         trans.parent = p.transform;
  33.                                         trans.localScale = Vector3.one;
  34.                                         return p;
  35.                                 }
  36.                         }
  37.                 }
  38.  
  39.                 // If we are working with a different UI type, we need to treat it as a brand-new one instead
  40.                 if (root != null)
  41.                 {
  42.                         UICamera cam = root.GetComponentInChildren<UICamera>();
  43.  
  44. #if UNITY_4_3 || UNITY_4_5 || UNITY_4_6
  45.                         if (cam != null && cam.camera.isOrthoGraphic == advanced3D)
  46. #else
  47.                         if (cam != null && cam.GetComponent<Camera>().orthographic == advanced3D)
  48. #endif
  49.                         {
  50.                                 trans = null;
  51.                                 root = null;
  52.                         }
  53.                 }
  54.  
  55.                 // If no root found, create one
  56.                 if (root == null)
  57.                 {
  58.                         GameObject go = NGUITools.AddChild(null, false);
  59.                         root = go.AddComponent<UIRoot>();
  60.  
  61.                         // Automatically find the layers if none were specified
  62.                         if (layer == -1) layer = LayerMask.NameToLayer("UI");
  63.                         if (layer == -1) layer = LayerMask.NameToLayer("2D UI");
  64.                         go.layer = layer;
  65.  
  66.                         if (advanced3D)
  67.                         {
  68.                                 go.name = "UI Root (3D)";
  69.                                 root.scalingStyle = UIRoot.Scaling.Constrained;
  70.                         }
  71.                         else
  72.                         {
  73.                                 go.name = "UI Root";
  74.                                 root.scalingStyle = UIRoot.Scaling.Flexible;
  75.                         }
  76.                 }
  77.  
  78.                 // Find the first panel
  79.                 UIPanel panel = root.GetComponentInChildren<UIPanel>();
  80.  
  81.                 if (panel == null)
  82.                 {
  83.                         // Find other active cameras in the scene
  84.                         Camera[] cameras = NGUITools.FindActive<Camera>();
  85.  
  86.                         float depth = -1f;
  87.                         bool colorCleared = false;
  88.                         int mask = (1 << root.gameObject.layer);
  89.  
  90.                         for (int i = 0; i < cameras.Length; ++i)
  91.                         {
  92.                                 Camera c = cameras[i];
  93.  
  94.                                 // If the color is being cleared, we won't need to
  95.                                 if (c.clearFlags == CameraClearFlags.Color ||
  96.                                         c.clearFlags == CameraClearFlags.Skybox)
  97.                                         colorCleared = true;
  98.  
  99.                                 // Choose the maximum depth
  100.                                 depth = Mathf.Max(depth, c.depth);
  101.  
  102.                                 // Make sure this camera can't see the UI
  103.                                 c.cullingMask = (c.cullingMask & (~mask));
  104.                         }
  105.  
  106.                         // Create a camera that will draw the UI
  107.                         Camera cam = NGUITools.AddChild<Camera>(root.gameObject, false);
  108.                         cam.gameObject.AddComponent<UICamera>();
  109.                         cam.clearFlags = colorCleared ? CameraClearFlags.Depth : CameraClearFlags.Color;
  110.                         cam.backgroundColor = Color.grey;
  111.                         cam.cullingMask = mask;
  112.                         cam.depth = depth + 1f;
  113.  
  114.                         if (advanced3D)
  115.                         {
  116.                                 cam.nearClipPlane = 0.1f;
  117.                                 cam.farClipPlane = 4f;
  118.                                 cam.transform.localPosition = new Vector3(0f, 0f, -700f);
  119.                         }
  120.                         else
  121.                         {
  122.                                 cam.orthographic = true;
  123.                                 cam.orthographicSize = 1;
  124.                                 cam.nearClipPlane = -10;
  125.                                 cam.farClipPlane = 10;
  126.                         }
  127.  
  128.                         // Make sure there is an audio listener present
  129.                         AudioListener[] listeners = NGUITools.FindActive<AudioListener>();
  130.                         if (listeners == null || listeners.Length == 0)
  131.                                 cam.gameObject.AddComponent<AudioListener>();
  132.  
  133.                         // Add a panel to the root
  134.                         panel = root.gameObject.AddComponent<UIPanel>();
  135. #if UNITY_EDITOR
  136.                         UnityEditor.Selection.activeGameObject = panel.gameObject;
  137. #endif
  138.                 }
  139.  
  140.                 if (trans != null)
  141.                 {
  142.                         // Find the root object
  143.                         while (trans.parent != null) trans = trans.parent;
  144.  
  145.                         if (NGUITools.IsChild(trans, panel.transform))
  146.                         {
  147.                                 // Odd hierarchy -- can't reparent
  148.                                 panel = trans.gameObject.AddComponent<UIPanel>();
  149.                         }
  150.                         else
  151.                         {
  152.                                 // Reparent this root object to be a child of the panel
  153.                                 trans.parent = panel.transform;
  154.                                 trans.localScale = Vector3.one;
  155.                                 trans.localPosition = Vector3.zero;
  156.                                 SetChildLayer(panel.cachedTransform, panel.cachedGameObject.layer);
  157.                         }
  158.                 }
  159.                 return panel;
  160.         }

arkon3

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 71
    • View Profile
Re: Moving prefab into Hierarchy on U5 broken
« Reply #6 on: March 19, 2015, 04:30:32 PM »
That worked thanks. Glad to see someone supporting plugins on Unity5. I wish more people did.

arkon3

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 71
    • View Profile
Re: Moving prefab into Hierarchy on U5 broken
« Reply #7 on: March 19, 2015, 09:04:49 PM »
Sorry to be the bearer of bad news. It still doesn't work correctly.  If you have a nested prefab is splits it into 2 parts when you drag it from hierarchy to project window. like this:

Hierarchy
UIRoot
>Camera
>>Panel
>>>Sprite (prefab)
>>>>Label

if you drag this from here to project this happens;

Hierarchy
UIRoot
>Camera
>>Panel
>>>Sprite (prefab)
>>>Label  <--- this moves up a level and gets left behind

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Moving prefab into Hierarchy on U5 broken
« Reply #8 on: March 21, 2015, 09:25:11 PM »
I wonder if it's GetComponentInParent<> that got broken in Unity 5... it's like it's not finding it anymore.

Try opening up NGUITools.cs, line 1053 (FindInParents<T> function) and changing it to include only the code inside the #if UNITY_4_3 section.
  1.         static public T FindInParents<T> (Transform trans) where T : Component
  2.         {
  3.                 if (trans == null) return null;
  4.  #if UNITY_FLASH
  5.                 object comp = trans.GetComponent<T>();
  6.  #else
  7.                 T comp = trans.GetComponent<T>();
  8.  #endif
  9.                 if (comp == null)
  10.                 {
  11.                         Transform t = trans.transform.parent;
  12.  
  13.                         while (t != null && comp == null)
  14.                         {
  15.                                 comp = t.gameObject.GetComponent<T>();
  16.                                 t = t.parent;
  17.                         }
  18.                 }
  19.  #if UNITY_FLASH
  20.                 return (T)comp;
  21.  #else
  22.                 return comp;
  23.  #endif
  24.         }

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Moving prefab into Hierarchy on U5 broken
« Reply #9 on: March 21, 2015, 09:28:13 PM »
And if that doesn't work, replace UIPanel.Find function (line 1819) with this:
  1.         static public UIPanel Find (Transform trans, bool createIfMissing, int layer)
  2.         {
  3.                 UIPanel panel = NGUITools.FindInParents<UIPanel>(trans);
  4.                 if (panel != null) return panel;
  5.                 while (trans.parent != null) trans = trans.parent; // <-- this gets added
  6.                 return createIfMissing ? NGUITools.CreateUI(trans, false, layer) : null;
  7.         }

arkon3

  • Jr. Member
  • **
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 71
    • View Profile
Re: Moving prefab into Hierarchy on U5 broken
« Reply #10 on: March 24, 2015, 05:42:43 PM »
Do i still need to add all these patches in or have you updated and fixed it in a new release?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Moving prefab into Hierarchy on U5 broken
« Reply #11 on: March 25, 2015, 12:07:31 PM »
3.8.1 was released prior to this thread, so these changes will be in 3.8.2.