Search Unity

Not sure how to handle UI prefabs in case of NGUI

Discussion in 'Prefabs' started by bac9-flcl, Jun 27, 2018.

  1. bac9-flcl

    bac9-flcl

    Joined:
    Dec 5, 2012
    Posts:
    829
    The implementation looks awesome so far!

    The only problem I've hit is the fact that the way Prefab Mode works seems to be incompatible with any components that execute in editor and rely on some objects being present in parents beyond the scope of a prefab.

    Since Prefab Mode seems to work by instantiating a copy of a prefab as an isolated root-level object, any checks for presence of parent components can easily fail. On components equipped to actively fix that (e.g. by creating a "missing" UI and parenting an "orphan" UI widget to it), this can even lead to Prefab Mode breaking altogether, with all objects created for use in it being stolen from hierarchy and moved into scene context.

    This applies to stuff like prefabs done on camera child objects requiring Camera component in parents, but most obvious example would be the popular NGUI UI system. None of its widgets (components inheriting from UIRect) can function without a UIRoot component being present somewhere higher in the hierarchy. If they detect absense of a parent with UIRoot, such parent object is created and UI widget is forcibly reparented to it. What this means in practice is that creating a prefab out of part of NGUI hierarchy (like a button) and attempting to enter Prefab Mode to edit it would trigger the following:

    - Prefab Mode instantiates a copy of button contents
    - ExecuteInEditor attribute allows initialization methods to run on all UI components
    - Components notice they have no UIRoot above them (since Prefab Mode instantiated the button as lone root-level hierarchy)
    - NGUI finds an existing UIRoot or creates a new object with it
    - Button hierarchy Prefab Mode prepared for use is forcibly yanked away under that UIRoot, leaving you with a completely empty Hierarchy view

    This doesn't just prevent me from editing prefabs made out of parts of NGUI UI hierarchy - after instantiated object hierarchies created on entry to Prefab Mode are "stolen", they remain in the scene indefinitely, polluting it (entering Prefab Mode on an NGUI-derived prefab would leave you with 10 copies of its hierarchy left in the scene). It's probably worth forcing Prefab Mode to keep a direct reference to created root object and destroy it even if it's no longer sitting where Prefab Mode expects it to.

    I'm not sure how to fully solve this elegantly. One possible step would be to modify the GetComponentInParent<T> method so that in Prefab Mode, it checks not just temporary hierarchy created for Prefab Mode, but full hierarchy above the prefab instance in the scene, allowing any code on components not to freak out about suddenly missing parents. That still leaves some missing pieces, though - for instance, what if components within a prefab require a function on out-of-prefab parent to run to initialize properly? Then we get into the woods of having not just to lie about parents to the prefab denizens, but also having to lie about children to objects sitting above prefabs, which gets hairy real quick. Making Prefab Mode work directly on in-scene hierarchy instead of independently instantiated set of objects would be ideal, I suppose, but there are probably technical challenges complicating that.

    What do you think? Maybe there is some clean workaround I'm not seeing?

    P.S.: I'll attempt to modify parts of NGUI to remove the need for parent root on initialization of widgets, but this is an issue which users without the means to do fixes like are bound to eventually encounter. :)
     
    Last edited: Jun 27, 2018
  2. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    Hi,

    Approaches where the Prefab will look into objects from the user scene that is open are problematic - Prefab Mode needs to work in isolation. You can open a Prefab Asset for editing in Prefab Mode from the Project window, even at a time when there's no scene open that has any instances of that Prefab. So we likely won't go down that route, but there are many other possible solutions.

    For built-in UI elements, which rely on Canvas, we either auto-generate a Canvas parent, or you can specify a special scene file to use as environment for UI Prefabs (Prefabs that have a RectTransform on the root GameObject) and then Prefab Mode will make the Prefab a child of whatever Canvas you have placed in that scene.

    I think we need to somehow generalize this approach and let users or user code recognize special types of objects as well, and let it provide scenes to use with marked GameObjects to use as parent for the Prefab.

    There are many ways this could be done specifically, and it will take some time to figure out the best approach. I'm not sure we will be able to solve this for the initial release. Do please keep us updated on how it goes trying to work around the issue with NGUI. :)
     
  3. bac9-flcl

    bac9-flcl

    Joined:
    Dec 5, 2012
    Posts:
    829
    Thanks for a quick reply!

    Editing Prefab Assets from Project window has exact same issue - UI widgets are initialized, realize they have no UIRoot parent, and escape away into a separate auto-generated root object.


    ^ What was dragged into Project window from scene hierarchy to create the Prefab Asset


    ^ What you see when entering Prefab Mode from Project window

    I think you're onto something with the native UI workaround. It can probably be generalized along these lines in the Prefab editing environment settings.

    - Beyond standard scene and native UI scene fields, provide an additional list of "special-needs component info", so to speak.
    - The list is using a simple container type with the following fields: with a "type" string field, a "scene" Scene Asset reference field, and a "parent" string field
    - You fill entries in that list: first string gets the Component type name (for example, "UIWidget"), second field gets a Scene Asset reference containing a setup allowing that component to work (e.g. "SceneWithUIRoot.scene"), and a third field tells us what scene object should act as a parent receiving the prefab content (for example "UIRoot_Object").
    - Prefab Mode scans all top level components of a prefab about to be opened in it and checks if there are any matches with type names in the special-needs list we've set up.
    - If there is a match (for example, root prefab object contains a "UIWidget" component we named in the list), we load the scene referenced in the special-needs entry, attempt to find an object named in that entry, and finally parent all content of a prefab to it (without showing that in the Prefab Mode hierarchy, just like you don't show UI environment for UI elements right now)
    - Voila, all components dependent on parent help (like NGUI widgets) are able to do their thing now

    This can probably be made prettier and easier to use (for example, using a typeof field instead of a string and having a component dropdown akin to Add Component menu to fill it would be far more elegant and error-proof than manually typing component name into a field). Hopefully this idea helps you!
     
  4. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    Yeah, that's very close to one of the ideas we discussed here. Only, we'd probably mark which object to use as parent inside the scene file itself with a tag or similar. Being able to mark a GameObject to use as parent has been requested independently of this "spceial need components" issue, so it could solve two things at once.
     
  5. bac9-flcl

    bac9-flcl

    Joined:
    Dec 5, 2012
    Posts:
    829
    Yeah, having a tag field would be a more elegant solution than a typo-prone text field that has to be updated manually!
     
  6. bac9-flcl

    bac9-flcl

    Joined:
    Dec 5, 2012
    Posts:
    829
    What is the correct way to detect whether you are currently in Prefab Mode? The only way I see so far is to check for PrefabUtility.IsPartOfAnyPrefab and then check for whether a GameObject returned by PrefabUtility.GetOutermostPrefabInstanceRoot has no parents, but that feels very dirty - I must be missing something. Having a reliable way to detect whether I'm in Prefab Mode (or just in a prefab instance in normal scene context) would allow me to mitigate the issue more easily.

    Edit: Ah wait, nope, Prefab Mode is not a traditional prefab state and PrefabUtility.IsPartOfAnyPrefab returns false in there. Maybe I can do something with scene name object is in...

    Edit: Yep, looks like I can fairly reliably detect I'm in Prefab Mode by traversing hierarchy until I hit a root object and comparing root.name to root.scene.name (additionally, I can check for mismatch of active scene and current object scene). If names of root object and scene its in match, we're in Prefab Mode. I suppose this means Prefab Mode works internally by creating a temporary scene? :)
     
    Last edited: Jun 28, 2018
  7. bac9-flcl

    bac9-flcl

    Joined:
    Dec 5, 2012
    Posts:
    829
    I failed to make NGUI work without a parent panel for now.

    But I found a reasonable workaround. I disabled reparenting to panels on widgets when they are in Prefab Mode, which prevents any NGUI prefab contents from flying away (and prevents them from successfully rendering, just like standard UI would fail without a canvas). Now that prefabs don't fall apart when opened, I can leverage Prefab Mode for object management (removing elements etc.), even though I can't visually edit UI while in it. I keep visual editing in traditional scene mode, and it seems to work quite well. :)

    Experimented with some simple nested setups so far - making window prefabs where buttons are their own prefabs. Everything seems to work well - even with the Prefab Mode issue discussed in this thread, this build already enables enormous workflow improvements.

    Edit: Looks like I'll have to stop testing - removal of ability to edit root level components on prefabs in the project seems to have broken any way to configure sprites in NGUI, which blocks me from doing further work on test UI I've been putting together.
     
    Last edited: Jun 28, 2018
  8. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    The best solution for this depends on whether you need to detect that you're not in main stage (the scenes) or if you need to specifically detect that you're in Prefab Mode. The difference is theoretical for now, but in future versions we'll likely have other types of stages that are neither main stage nor Prefab Stage.

    To check if you're not in main stage:
    UnityEditor.SceneManagement.StageUtility.GetCurrentStage() !=  UnityEditor.SceneManagement.StageUtility.GetMainStage()


    To check if you're specifically in Prefab Mode - this is experimental API so may change and break in future versions:
    UnityEditor.Experimental.SceneManagement.PrefabStageUtility.GetCurrentPrefabStage() != null
     
  9. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    Thanks for sharing this!

    All right. Sprites can't be configured on Prefab instances and applied with NGUI? Was this always the case or is this a new limitation? I assume the reason that can't be configure in Prefab Mode is the issue that they're not visible (as you discussed), so you'd be editing blindly?
     
  10. bac9-flcl

    bac9-flcl

    Joined:
    Dec 5, 2012
    Posts:
    829
    Thanks for detailing how Prefab Mode can be detected!

    As about sprites: I'm able to configure sprites (widgets in UI hierarchy), but I'm unable to configure the atlas used by those sprites. Similarly to standard Unity UI, NGUI generates atlases out of sprite textures, except it stores atlas metadata (describing stuff like corners where sprite begins and ends on atlas texture, offsets for 9-slicing, margins etc.) on a prefab object with a root-level inspector.



    Since new prefab system removed inspector rendering on prefabs selected in Project view, I'm no longer able to access the sprite configuration manager that lives on root level of atlas prefab. Entering Prefab Mode to do it seems to break it in a few ways, not sure what's up there.

    Anyway, this is a really niche problem which I'm sure would be fixed on NGUI side once nested prefabs are introduced in mainline Unity releases. Having a way to load Prefab Mode under specially prepared hierarchies (what was proposed further up in this thread) is the actually important feature request I have, while this issue (while blocking me now) can be resolved by moving atlas configuration from top level prefab inspectors to any number of other potential places, like editor window or a scriptable object. So don't worry about it. :)
     
    runevision likes this.
  11. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    What's a stage? How is it different from a scene?
     
  12. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    A stage is an isolated context comprising one or more scenes. All the loaded (regular) scenes together is one stage (the main stage). Each Prefab opened in Prefab Mode is a separate stage (the Prefab contents is loaded into a temporary preview scene). In the breadcrumbs, each breadcrumb represents one stage.
     
  13. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,334
    Is this a new concept that's been introduced to facilitate the prefab stuff, or is just just new that it's exposed through a public API?
     
  14. Deeeds

    Deeeds

    Joined:
    Mar 15, 2018
    Posts:
    739
    I read somewhere that the new prefabs are basically just self contained scenes, holding the objects that make up the prefab. Is this somewhat true, and therefore the reasoning for the creation of stages as a wrapper for multiple scenes/prefabs?
     
  15. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    It's a new concept. We're not raising a lot of attention about it since it's not really needed in order to understand how to use Prefab Mode, so the term Stage is not mentioned in the manual. But once you go into the scripting side of things, you'll need to understand it.
     
  16. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    Yep. If you inspect a text-serialized scene and a text-serialized Prefab, you'll see that the format is the same.

    There are multiple reasons for creating stages.

    One reason is that the Prefab contents need to be kept separate from the content in the regular scenes (the main stage). You don't want object from inside Prefab Mode interacting with objects in the regular scenes.

    Another reason is that we needed something to represent what's shown in the Scene/Hierarchy at once. Normally you see all the loaded scenes, and when you're in Prefab Mode you see the Prefab contents. What do you call "everything shown at a given time in the Scene view and Hierarchy"? We couldn't call it a "scene" because that already means something different, and you can see multiple scenes at the same time in the Scene view / Hierarchy. We chose to call the new concept "stage".
     
  17. Deeeds

    Deeeds

    Joined:
    Mar 15, 2018
    Posts:
    739
    Nested Scenes?

    ;)
     
    dri_richard likes this.
  18. Deeeds

    Deeeds

    Joined:
    Mar 15, 2018
    Posts:
    739
    I'm not aware of this. How is this so, and where is this introduced? I feel like I'm missing something profound in understanding how Unity works.

    I thought it was a single Scene at a time, each representing a stage or level of a game.

    Has this recently changed, or have I completely missed this in my (very limited) experience with Unity?
     
  19. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    Multi-scene editing was introduced in Unity 5.3 and is documented here:
    https://docs.unity3d.com/Manual/MultiSceneEditing.html
     
    Baste likes this.
  20. Deeeds

    Deeeds

    Joined:
    Mar 15, 2018
    Posts:
    739
    Argh, wonderful. Thank you.

    Given the naming of Animator and Animation (within Unity), what a user does to multiple scenes should be called a Direction, and the controller a Director.

    Stage should be reserved for an aspect of the player's limited perspective into what's produced.
     
  21. bac9-flcl

    bac9-flcl

    Joined:
    Dec 5, 2012
    Posts:
    829
    I think Stage is an appropriate name for this new concept (stage as in a place containing things that are presented). As about multi-scene support, the ship of naming it has probably sailed a while ago :)
     
  22. bac9-flcl

    bac9-flcl

    Joined:
    Dec 5, 2012
    Posts:
    829
    Are there any changes related to this in the new 2018.3 beta? Specifically, was a generalized editing parent scene system added in place of Unity UI-exclusive parent scene override?
     
    Deeeds likes this.
  23. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    No, no change there I'm afraid. We have been busy just stabilizing things. New design changes like this won't happen for the initial release.

    As a temporary solution, there might be some things you can do with the callback
    PrefabStage.prefabStageOpened
    in the experimental namespace UnityEditor.Experimental.SceneManagement.
     
  24. Shaun-Peoples

    Shaun-Peoples

    Joined:
    Feb 26, 2013
    Posts:
    24
    Thanks to @bac9-flcl for pointing me in the right direction, here's something that may help others to work with the new Prefab workflows and NGUI. It's a bit of a hack as it injects code into the Editor DLL and hooks into the UIDrawCall.Create function as well - but until there's a more robust way to define Stage roots, this works for now.

    No guarantee that it's flawless for all situations, but I've managed to work with prefabs using NGUI that don't have panel components in the root object and also intermixes in TextMeshPro child objects in the prefab hierarchy:

    https://github.com/shaundg/NGUIPrefabStagePatching
     
  25. Shaun-Peoples

    Shaun-Peoples

    Joined:
    Feb 26, 2013
    Posts:
    24
    Updated to be more flexible and work with b11 from @bac9-flcl
     
  26. bretternst

    bretternst

    Joined:
    Apr 8, 2017
    Posts:
    6
    Here's the generalized solution I've been using in b12, and it seems to work nicely so far. Instead of using environment scenes, I just use environment prefabs that can be specified on a per-prefab basis by adding a component on the root. One nice thing about doing it this way is that the environment prefab can contain multiple "slots" for different edited prefabs (instead of just having one marked GameObject) which is handy if you're composing different parts of a UI.

    Code (CSharp):
    1. #if UNITY_EDITOR
    2. using UnityEditor;
    3. using UnityEditor.Experimental.SceneManagement;
    4. using UnityEngine;
    5. using UnityEngine.SceneManagement;
    6.  
    7. public static class PrefabEditorHelper {
    8.     public static void UsePrefabAsset(GameObject obj, string prefabPath, string parentName = "PrefabContainer") {
    9.         var prefabStage = PrefabStageUtility.GetPrefabStage(obj);
    10.         if (prefabStage != null && obj.transform.parent == null) {
    11.             var instance = PrefabUtility.InstantiatePrefab(
    12.                 AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath)) as GameObject;
    13.             if (instance) {
    14.                 SceneManager.MoveGameObjectToScene(instance, obj.scene);
    15.                 var container = FindObjectRecursive(instance, parentName);
    16.                 if (container) {
    17.                     obj.transform.SetParent(container.transform, false);
    18.                 }
    19.                 else {
    20.                     Debug.LogWarning("No object named " + parentName + " found in environment prefab " + prefabPath);
    21.                 }
    22.             }
    23.             else {
    24.                 Debug.LogWarning("Could not find environment prefab: " + prefabPath);
    25.             }
    26.         }
    27.     }
    28.  
    29.     static GameObject FindObjectRecursive(GameObject obj, string name) {
    30.         if (obj.name == name)
    31.             return obj;
    32.      
    33.         for (var i = 0; i < obj.transform.childCount; i++) {
    34.             var go = FindObjectRecursive(obj.transform.GetChild(i).gameObject, name);
    35.             if (go != null)
    36.                 return go;
    37.         }
    38.  
    39.         return null;
    40.     }
    41. }
    42. #endif
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. [ExecuteAlways]
    4. public class UseEnvironmentPrefab : MonoBehaviour {
    5.    public string prefabPath;
    6.    public string containerName = "PrefabContainer";
    7.  
    8. #if UNITY_EDITOR
    9.    void Awake() {
    10.        if (!string.IsNullOrEmpty(prefabPath))
    11.            PrefabEditorHelper.UsePrefabAsset(gameObject, prefabPath, containerName);
    12.    }
    13. }
     
    Last edited: Dec 4, 2018
    bac9-flcl likes this.
  27. Mads-Nyholm

    Mads-Nyholm

    Unity Technologies

    Joined:
    Aug 19, 2013
    Posts:
    217
    Great use of the new PrefabStage loading approach we added in b12.

    We also want to add a Editor-only tag you can use for tagging which GameObject should be the Prefab root parent. Then you don't need to search by name for that GameObject (suggested by Shaun-Peoples here: https://forum.unity.com/threads/creating-prefab-editing-environments.574795/)
     
  28. bretternst

    bretternst

    Joined:
    Apr 8, 2017
    Posts:
    6
    An editor-only tag would be very useful, but I have some cases where having multiple possible slots for different prefabs in the same environment is helpful for composing heavily UI-based applications. That said, I’m happy to be able to implement this myself in Awake().

    The real value here, of course, is the ability to choose different environments which I think time will reveal to be a critically important capability. I look forward to seeing how this evolves.
     
  29. bac9-flcl

    bac9-flcl

    Joined:
    Dec 5, 2012
    Posts:
    829
    @Mads-Nyholm
    Could you explain how to access prefab root using Awake/OnEnable? I'm trying to implement a generic helper method that reparents any UI hierarchy if no UIPanel was found in the prefab stage hierarchy, but I'm a bit stuck because I don't see any way to get a reference to actual object I want to reparent - prefab root. In MovePrefabRootToEnvironmentScene I had access to prefab contents root object, but when I attempt to use PrefabStage.prefabContentsRoot from component Awake in rc1 or beta 12, I get the following error:

    Code (csharp):
    1. InvalidOperationException: Requesting 'prefabContentsRoot' from Awake and OnEnable are not supported
    There is another alternative method of grabbing root object (or, rather, root objects), which is Scene.GetRootGameObjects, but it doesn't work either:

    Code (csharp):
    1. ArgumentException: The scene is not loaded.
    2. UnityEngine.SceneManagement.Scene.GetRootGameObjects (System.Collections.Generic.List`1[T] rootGameObjects) (at C:/buildslave/unity/build/Runtime/Export/SceneManager/Scene.cs:90)
    3. UnityEngine.SceneManagement.Scene.GetRootGameObjects () (at C:/buildslave/unity/build/Runtime/Export/SceneManager/Scene.cs:74)
    Without either of those, how can I reparent the prefab content root?
     
    Last edited: Dec 8, 2018
  30. bac9-flcl

    bac9-flcl

    Joined:
    Dec 5, 2012
    Posts:
    829
    Okay, here is the patch that seems to work - it ignores both of these built-in ways of getting to roots and instead manually iterates through parent chain. This can be added directly to NGUI UIWidget code or used as a Harmony patch:

    Code (csharp):
    1. [HarmonyPatch (typeof (UIWidget))]
    2. [HarmonyPatch ("Awake")]
    3. public class PatchUIWidget
    4. {
    5.     static void Prefix (UIWidget __instance)
    6.     {
    7.         var gameObject = __instance.gameObject;
    8.  
    9.         var prefabStage = PrefabStageUtility.GetPrefabStage (gameObject);
    10.         if (prefabStage == null)
    11.             return;
    12.  
    13.         var rootsInParents = gameObject.GetComponentsInParent<UIRoot> (true);
    14.         var panelsInParents = gameObject.GetComponentsInParent<UIPanel> (true);
    15.  
    16.         bool missingRoot = rootsInParents.Length == 0;
    17.         bool missingPanel = panelsInParents.Length == 0;
    18.  
    19.         if (!missingRoot && !missingPanel)
    20.             return;
    21.  
    22.         // This way of getting to root is necessary since prefabContentsRoot and GetRootGameObjects aren't available at this point
    23.         var instanceRoot = gameObject.transform;
    24.         while (instanceRoot.parent != null)
    25.             instanceRoot = instanceRoot.parent;
    26.  
    27.         GameObject container = EditorUtility.CreateGameObjectWithHideFlags ("UIRoot (Environment)", HideFlags.DontSave);
    28.         container.layer = LayerMask.NameToLayer ("UI");
    29.  
    30.         if (missingRoot)
    31.             container.AddComponent<UIRoot> ();
    32.  
    33.         if (missingPanel)
    34.             container.AddComponent<UIPanel> ();
    35.  
    36.         SceneManager.MoveGameObjectToScene (container, prefabStage.scene);
    37.         instanceRoot.SetParent (container.transform, false);
    38.     }
    39. }
     
  31. Mads-Nyholm

    Mads-Nyholm

    Unity Technologies

    Joined:
    Aug 19, 2013
    Posts:
    217
    @bac9-flcl The Awake is called while the scene is being loaded, that is why
    scene.GetRootGameObjects()
    is not allowed to be called yet. And the PrefabStage is also fully setup after loading the scene (and after the Awake calls) so only at that time the
    prefabContentsRoot
    is cached.

    Is this Prefix method called for all Awake calls of UIWidgets in the Prefab?
    If so it should be enough to just create the parent environment when
    gameObject.transform.parent == null
    (and otherwise early out).
     
  32. bac9-flcl

    bac9-flcl

    Joined:
    Dec 5, 2012
    Posts:
    829
    @Mads-Nyholm Makes sense why these shortcuts don't work in Awake, thanks!

    I'm not sure what null check for parents would accomplish since absolute majority of UI widgets would already have a parent - every single sprite, container, texture etc. are widgets, after all. Most of them wouldn't be root objects. I agree that doing a GetComponentsInParent per each isn't ideal, though. I'd add an early out check for an enabled widget higher up in the hierarchy (in that case we can safely leave the responsibility of doing all this that widget), and I'd swap array-based component fetching to single-component fetching since we only use GetComponentsInParent to check if there are no results. Maybe there are more elegant solutions, though, like having an early out based on encountering a root level tag indicating that environment setup was complete; or checking for some sort of a static bool that is flipped on when setup is performed and flipped off when you exit prefab stage.
     
  33. jayatubi

    jayatubi

    Joined:
    Dec 9, 2013
    Posts:
    143
    Hi,

    I tried your solution. The UIRoot/UIPanel could be created but how about the UIDrawCalls? I can't see any visual of the UI elements in the prefab edit scene.

    It looks like any game objects which are not a part of the editing prefab will be auto removed from the scene and the UIDrawCalls were created outside the UIRoot.
     
  34. andyz

    andyz

    Joined:
    Jan 5, 2010
    Posts:
    2,269
    Did anyone get an NGUI project working in 2018.4? I think I need to try an update to NGUI
     
    Last edited: Jun 19, 2019
  35. bac9-flcl

    bac9-flcl

    Joined:
    Dec 5, 2012
    Posts:
    829
    As far as I know, up to date releases work great with the new prefab system out of the box.