Search Unity

Runtime Inspector and Hierarchy [Open Source]

Discussion in 'Assets and Asset Store' started by yasirkula, Oct 22, 2017.

  1. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Hello there,

    While working on a project that needed some sort of in-game editor for a while, I have developed a runtime Inspector and Hierarchy solution that works similar to Unity's own Hierarchy and Inspector views.

    Asset Store: https://assetstore.unity.com/packages/tools/gui/runtime-inspector-hierarchy-111349
    Also available at: https://github.com/yasirkula/UnityRuntimeInspector/
    Discord: https://discord.gg/UJJt549AaV
    GitHub Sponsors ☕

    DarkSkin.png

    FEATURES
    • The hierarchy costs 1 SetPass call and ~4 batches (assuming that Sprite Packing is enabled in Editor Settings)
    • The inspector costs 1 SetPass call and ~10 batches (assuming that Sprite Packing is enabled in Editor Settings)
    • Both panels are heavily optimized in terms of GC in order not to generate any unnecessary garbage. By default, both the inspector and the hierarchy are refreshed every frame to reflect any changes to their user interface immediately. This generates some garbage especially for the inspector as, most of the time, the inspected object has variables of value types. These variables are boxed when accessed via reflection and this boxing creates some unavoidable garbage. However, this process can be greatly optimized by increasing the Refresh Interval of the inspector and/or the hierarchy
    • Includes a built-in color picker and a reference picker:
    Pickers.png
    • Visual appearance of the inspector and the hierarchy can be tweaked by changing their Skin. There are two premade skins included in the Skins directory: LightSkin and DarkSkin. You can create your own skins using the Assets-Create-yasirkula-RuntimeInspector-UI Skin context menu
    LightSkin.png

    You can visit the repo for more info.

    Enjoy!
     
    Last edited: May 31, 2023
    xucian, Bonnye, DaniStoll and 6 others like this.
  2. Frednaar

    Frednaar

    Joined:
    Apr 18, 2010
    Posts:
    153
    Very nice !
    Thanks for sharing this
     
  3. nikix22

    nikix22

    Joined:
    Jan 16, 2015
    Posts:
    25
    This is funtastic! I tried it and works perfect! Thank you very much! ;)
     
  4. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
  5. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
  6. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    Hi,
    Great asset!

    Although I have a problem: I use the default hierarchy prefab, but the hierarchy is empty when running in the player (android, win). In the editor it works fine. Can you tell me what to look for?
    Using unity 2017.2.0f3

    Edit:
    1) tested with 2017.3.1f1 and it works
    2) in 2017.3.0f1 added Mask instead of RectMask2D and it works
    Maybe this helps. Have a nice day :)
     
    Last edited: Mar 17, 2018
  7. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Thank you for all the information. I'll definitely look into it.
     
  8. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    While reproducing the issue on Unity 2017.2.0f3, I also noticed that some of my sprites were looking ugly in that version of Unity. In fact, it was the case for some of my other plugins, as well.

    Anyways, after adding these two lines to the Awake function of SkinnedWindow.cs, the problem disappeared on Unity 2017.2.0f3.

    Code (CSharp):
    1. gameObject.SetActive( false );
    2. gameObject.SetActive( true );
    It also works fine on Unity 2017.3.0p2 but I don't have Unity 2017.3.0f1 installed so I couldn't test it on that version.

    I've pushed an update to the GitHub repository and will push an update to the Asset Store version, as well. The update includes a bugfix for those terrible sprites, too.
     
  9. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,188
    Great asset. The only issue I noticed was it can sometimes be hard to click on the little arrows, but that's a minor problem and not really an "issue".

    This asset helped us solve a problem in one of our apps after we swapped some stuff around.
     
    yasirkula likes this.
  10. eleicht

    eleicht

    Joined:
    Apr 21, 2016
    Posts:
    9
    Hi there,
    I love this asset, it's awesome and useful and I'm currently using it in a customer's project. However, I do have two severe issues I can't solve myself, concerning the Runtime Hierarchy:
    1. I need to use the slider like a normal slider, as you see it everywhere. It seems to work like something for a touch input, but that's not usable for me.
    2. I can't get a horizontal slider working. This seems to be an issue due to the massive use of content size fitters and layout groups, and I tried to get into this, but it's too complex for me to dig in (not the fitters themselves, but the use of it in the runtime hierarchy).

    Could you please provide some help for that? I would appreciate it a lot.
    Thanks in advance!
     
  11. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    There you go.
     

    Attached Files:

  12. Greg-Bassett

    Greg-Bassett

    Joined:
    Jul 28, 2009
    Posts:
    628
    Just had a play with your asset and its very good, one feature I would like is to be able to drag and drop GameObjects in the Hierarchy to parent them together or to unparent them, like you can with the Editor Hierarchy.

    Could this be added relatively easily?
     
  13. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Attaching the following script to RuntimeHierarch, HierarchyItemRoot and HierarchyItemTransform prefabs should do the trick:

    Code (CSharp):
    1. using UnityEngine;
    2. using RuntimeInspectorNamespace;
    3. using UnityEngine.EventSystems;
    4.  
    5. public class HierarchyOnDropParent : MonoBehaviour, IDropHandler
    6. {
    7.     private HierarchyItem target;
    8.  
    9.     private void Awake()
    10.     {
    11.         target = GetComponent<HierarchyItem>();
    12.     }
    13.  
    14.     public void OnDrop( PointerEventData eventData )
    15.     {
    16.         Transform droppedTransform = RuntimeInspectorUtils.GetAssignableObjectFromDraggedReferenceItem( eventData, typeof( Transform ) ) as Transform;
    17.         if( droppedTransform == null )
    18.             return;
    19.  
    20.         Transform newParent = ( target as HierarchyItemTransform ) != null ? ( (HierarchyItemTransform) target ).BoundTransform : null;
    21.         if( droppedTransform.parent == newParent )
    22.             return;
    23.  
    24.         if( newParent != null )
    25.         {
    26.             // Avoid setting child object as parent of the parent object
    27.             Transform curr = newParent;
    28.             while( curr.parent != null && curr.parent != droppedTransform )
    29.                 curr = curr.parent;
    30.  
    31.             if( curr.parent == droppedTransform )
    32.                 curr.SetParent( droppedTransform.parent, false );
    33.         }
    34.      
    35.         droppedTransform.SetParent( newParent, false );
    36.  
    37.         RuntimeHierarchy hierarchy = GetComponentInParent<RuntimeHierarchy>();
    38.         if( hierarchy != null )
    39.         {
    40.             hierarchy.Refresh();
    41.             hierarchy.Deselect();
    42.             hierarchy.Select( droppedTransform );
    43.         }
    44.     }
    45. }
     
    Last edited: May 1, 2018
    Greg-Bassett likes this.
  14. Greg-Bassett

    Greg-Bassett

    Joined:
    Jul 28, 2009
    Posts:
    628
    Wow! That was quick, I will try now! :)
     
  15. Greg-Bassett

    Greg-Bassett

    Joined:
    Jul 28, 2009
    Posts:
    628
    Just tried that and I can't drag and drop anything in the runtime Hierarchy? any ideas?
     
  16. Greg-Bassett

    Greg-Bassett

    Joined:
    Jul 28, 2009
    Posts:
    628
    Scratch that! Its does work, its just you have to hold the mouse down for a bit, as per setting Create Dragged Reference On Hold, and Dragged Reference Hold Time. Thank you!!!

    Only missing feature to match Editor Hierarchy is that when you drag over a parent object it would be nice if it expanded the sub objects so you can drop the object onto a child.
     
    Last edited: May 1, 2018
  17. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    You are welcome! In case you didn't know, you can also drop a "Dragged Reference" to Object slots in RuntimeInspector (if they are of compatible types).

    P.S. I've decided to add this feature to the plugin in the next update. Thanks for the idea!
     
    Greg-Bassett likes this.
  18. Greg-Bassett

    Greg-Bassett

    Joined:
    Jul 28, 2009
    Posts:
    628
    I didn't know that! That's perfect!!!

    It's also very kind that your making this available for FREE, I am very grateful to you!
     
    yasirkula likes this.
  19. eleicht

    eleicht

    Joined:
    Apr 21, 2016
    Posts:
    9
    Dear Sir, you are awesome!
    Thank you so very much for that, highly appreciated!
     
    Greg-Bassett and yasirkula like this.
  20. Marcos-Elias

    Marcos-Elias

    Joined:
    Nov 1, 2014
    Posts:
    159
    This is amazing! It makes so easy testing different values for our own games, making changes in runtime to see how they behave, without creating new debug canvas (this is too boring and time consuming).

    Is there a function to automatically select a specific game object? I would like to use for my vehicle, so it would begin with it selected.
     
  21. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Certainly there is!

    For RuntimeHierarchy: Select(Transform selection)
    For RuntimeInspector: Inspect(object obj)
     
    Marcos-Elias likes this.
  22. Patrascu

    Patrascu

    Joined:
    Jan 20, 2016
    Posts:
    59
    Any idea why the enum popups don't show up?
     
  23. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Is it only the enum fields that are missing? Otherwise, it might be caused by IL2CPP managed bytecode stripping. Does everything work fine while testing on Editor?

    I'm guessing that there are no error messages. Which Unity version & scripting backend are you using and what is your target platform?
     
  24. Patrascu

    Patrascu

    Joined:
    Jan 20, 2016
    Posts:
    59
    So far it's only enum fields that don't work. The fields aren't missing, the problem is that when I click on the field nothing happens, no pop-up menu shows up. This behavior is present both in the Editor and at Runtime.

    There are no errors or warnings showing up in the console either. I'm on Unity 2017.4.2f2 on the Nintendo Switch target platform with IL2CPP scripting backend (which is the only option for the Switch).
     
  25. Patrascu

    Patrascu

    Joined:
    Jan 20, 2016
    Posts:
    59
    The dropdown hierarchy is created just fine, it's just not visible. I've also noticed that there is a component called DropdownItem that is missing it's script on every item in the dropdown list. See the Inspector shot below:
    upload_2018-5-23_13-3-54.png
     
  26. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    It is missing for me as well, that shouldn't be the problem. If you put the RuntimeInspector on a plain/unedited canvas, does it change anything?
     
  27. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Here's a screenshot from my Dropdown List, is it the same for you:

    inspector.png

    Sorry about the green tint.
     
  28. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    Hi,
    Great asset.
    Here's my problem:

    I do the following:
    1. Start scene A with a game object that has has DontDestroyOnLoad
    2. Start scene B. add inspector+hierarchy as its children. browse the hierarchy+inspector. Disable them. This sometimes creates some garbage under the DontDestroyOnLoad scene (even if I'd destroy the hierarchy+inspector at this point, they'll still be there - but won't destroy them in this session).
    3. Start scene A. No additional inspector+hierarchy are created. The old ones are still there, under their old parent
    4. Start scene B. Errors:
    URL: https://ibb.co/fK9HD8
     
  29. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Can you try making the following change on both RuntimeInspector.cs and RuntimeHierarchy.cs:

    Code (CSharp):
    1. if( poolParentGO == null )
    2. {
    3.     poolParentGO = new GameObject( POOL_OBJECT_NAME );
    4.     DontDestroyOnLoad( poolParentGo );
    5. }
     
    xucian likes this.
  30. Greg-Bassett

    Greg-Bassett

    Joined:
    Jul 28, 2009
    Posts:
    628
    Hi,

    Quick question, whats the simplest way for me to edit the fields and properties displayed for each component type, I have looked at the Expose Private Properties and Expose Public Properties.

    For example the Transform component, I want to just show Position, Rotation and Scale, the same as the Editor, but the RuntimeInspector shows many more fields, such as Position and localPosition, EulerAngle etc...

    Which script should I edit, GameObjectField.cs?

    Thanks in advance!

    Greg
     
  31. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    You can add the TransformField prefab to the "Standard Drawers" of the InternalSettings asset or a new RuntimeInspector Settings asset (in which case, don't forget to add the new asset to the Settings property of the RuntimeInspector).

    EDIT: in case you wonder how I've created it, I've just duplicated the ObjectField prefab and replaced the ObjectField component with TransformField component.

    P.P.S. It is also possible to accomplish this task without creating any prefabs via the Hidden Variables and Exposed Variables of the InternalSettings asset (or a new RuntimeInspector Settings asset that is assigned to the RuntimeInspector). For complete documentation, see: https://github.com/yasirkula/UnityRuntimeInspector
     

    Attached Files:

    Last edited: May 23, 2018
    Greg-Bassett likes this.
  32. Greg-Bassett

    Greg-Bassett

    Joined:
    Jul 28, 2009
    Posts:
    628
    Many thanks for super fast reply, I will give it a go!
     
  33. Greg-Bassett

    Greg-Bassett

    Joined:
    Jul 28, 2009
    Posts:
    628
    OK, I have managed to use the Hidden Variables in the InternalSettings asset to hide unwanted fields which is great, but I was unable to get the TransformField prefab to work when replacing the ObjectField prefab in the Standard Drawers section of the InternalSettings asset, when I click the Transform component to expand it in the RuntimeInspector I get a number of log errors on screen and it does not expand the Transform component?
     
  34. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    You should add the TransformField to the end of the Standard Drawers list, instead of replacing the ObjectField. If that it already the case, which error are you getting?
     
  35. Greg-Bassett

    Greg-Bassett

    Joined:
    Jul 28, 2009
    Posts:
    628
    Perfect, that now works!!! :)
     
  36. Greg-Bassett

    Greg-Bassett

    Joined:
    Jul 28, 2009
    Posts:
    628
    Sorry for another question, but I am using an asset called GameFlow and in the Editor it displays components within each other as it allows you to perform actions on a GameObject, however the RuntimeInspector just lists the components one after another, see images below. How would you advise I modify RuntimeInspector to provide the same sort of layout with components shown within each other? Thanks in advance!

    unity_inspector.JPG runtime_inspector.JPG
     
  37. xucian

    xucian

    Joined:
    Mar 7, 2016
    Posts:
    846
    That solved it! Thanks buddy!
    This asset really speeds up our testing

    Cheers
     
    yasirkula likes this.
  38. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    @Greg-Bassett Firstly, you should filter out the components that you don't want to be visible directly underneath the GameObject. You can do so via the Refresh function of the GameObjectField. For example, to skip Renderer components, you can put the following inside the for loop:

    if( components[i] is Renderer )
    components.RemoveAt( i );


    Then you will have to create some custom drawers (like TransformField). I'm not sure how many will be necessary because I don't really know GameFlow's class hierarchy but one will certainly be necessary for GameFlow component and probably some more for base Condition/Event classes.

    Here's an example drawer code that displays all the Collider components attached to the GameObject under the MeshFilter component:

    Code (CSharp):
    1. #if !UNITY_EDITOR && NETFX_CORE
    2. using System.Reflection; // can be necessary for UWP platform
    3. #endif
    4. using RuntimeInspectorNamespace;
    5. using System;
    6. using System.Collections.Generic;
    7. using UnityEngine;
    8.  
    9. public class MeshFilterField : ExpandableInspectorField
    10. {
    11.     protected override int Length { get { return components.Count; } }
    12.        
    13.     private List<Component> components = new List<Component>( 2 );
    14.        
    15.     public override bool SupportsType( Type type )
    16.     {
    17.         return type == typeof( MeshFilter );
    18.     }
    19.  
    20.     protected override void OnUnbound()
    21.     {
    22.         base.OnUnbound();
    23.         components.Clear();
    24.     }
    25.  
    26.     protected override void GenerateElements()
    27.     {
    28.         for( int i = 0; i < components.Count; i++ )
    29.             CreateDrawerForComponent( components[i] );
    30.     }
    31.  
    32.     public override void Refresh()
    33.     {
    34.         base.Refresh();
    35.  
    36.         components.Clear();
    37.         if( !Value.IsNull() )
    38.         {
    39.             GameObject go = ( (MeshFilter) Value ).gameObject;
    40.             go.GetComponents( components );
    41.  
    42.             for( int i = components.Count - 1; i >= 0; i-- )
    43.             {
    44.                 if( components[i].IsNull() || !( components[i] is Collider ) )
    45.                     components.RemoveAt( i );
    46.             }
    47.         }
    48.     }
    49. }
    You can tweak it to work with GameFlow and/or other components. Then duplicate the TransformField prefab, replace its TransformField script with the new script and add the new prefab to the end of the Standard Drawers list.
     
  39. Greg-Bassett

    Greg-Bassett

    Joined:
    Jul 28, 2009
    Posts:
    628
    You sir are a legend!!! This asset is frigging awesome, and your support of it is second to none and super fast!

    Thank you so much, your asset is going to help me bring my product idea to life!!! I can't thank you enough!

     
    yasirkula likes this.
  40. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Glad it was helpful ^_^
     
    Greg-Bassett likes this.
  41. Patrascu

    Patrascu

    Joined:
    Jan 20, 2016
    Posts:
    59
    Okay, here are my findings.

    The enum pop-up UI doesn't work if the canvas it belongs to is set to Screen Space - Camera mode and has a custom sorting layer (other than Default). I solved the problem in my case by creating another Canvas that was set to Overlay mode.
     
  42. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Good catch! "Dropdown List"s Canvas has Default sorting layer by default, which causes the issue. Adding the following component to Dropdown fixed the issue for me:

    Code (CSharp):
    1. using System.Collections;
    2. using UnityEngine;
    3. using UnityEngine.EventSystems;
    4. using UnityEngine.UI;
    5.  
    6. public class DropdownLayerFix : MonoBehaviour, IPointerClickHandler, ISubmitHandler
    7. {
    8.     private Dropdown dropdown;
    9.    
    10.     private void Awake()
    11.     {
    12.         dropdown = GetComponent<Dropdown>();
    13.     }
    14.  
    15.     public void OnPointerClick( PointerEventData eventData )
    16.     {
    17.         StartCoroutine( FixCanvas() );
    18.     }
    19.  
    20.     public void OnSubmit( BaseEventData eventData )
    21.     {
    22.         StartCoroutine( FixCanvas() );
    23.     }
    24.  
    25.     private IEnumerator FixCanvas()
    26.     {
    27.         yield return null;
    28.  
    29.         Canvas dropdownCanvas = GetComponentInChildren<Canvas>();
    30.         if( dropdownCanvas != null )
    31.             dropdownCanvas.sortingLayerID = dropdown.captionText.canvas.sortingLayerID;
    32.     }
    33. }
     
    Patrascu likes this.
  43. coffiarts

    coffiarts

    Joined:
    Jan 7, 2013
    Posts:
    33
    Am I getting it right, that the hierarchy will NOT display Game Objects with "DontDestroyOnLoad" = true?
    Because in my case, I am not seeing any of them at runtime - only anything else.
     
  44. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    You are right. That's mainly because there is no standard way to access the objects under the DontDestroyOnLoad scene. There are indeed some ways to access them but the algorithm is a slow one; it would spike the CPU usage if called regularly.

    Nevertheless, I have a faster optional solution to this problem which makes use of pseudo-scenes. Simply create an empty GameObject, add PseudoSceneSourceTransform component to it, name the pseudo-scene and call DontDestroyOnLoad on that object when game starts. Now, if you make your root DontDestroyOnLoad objects children of this pseudo-scene object, they will appear in RuntimeHierarchy.
     
  45. dadude123

    dadude123

    Joined:
    Feb 26, 2014
    Posts:
    789
    That is a pretty awesome project.

    I'm personally working on something that would synergize pretty well with this: A visual script editor (similar to the Warcraft3 script editor, but can call all C# functions, other script functions, even create virtual "script-classes", debugging, breakpoints, ...)

    With those two projects together you could essentially make a game IN a unity game haha.
     
    yasirkula likes this.
  46. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    Now that would be next-gen!
     
  47. coffiarts

    coffiarts

    Joined:
    Jan 7, 2013
    Posts:
    33
    Thanks for this elegant solution, @yasirkula !
    Works fine for me - it forced me to do some redesign (as all DontDestroyOnLoad objects need to share one parent now), but it wasn't a big deal.
    With this addition, Runtime Inspector & Hierarchy really takes my workflow to another dimension of debugging (without being able to visualize DontDestroyOnLoad objects, it would have been only half way).

    :) :thumbsup:
     
    yasirkula likes this.
  48. wxxhrt

    wxxhrt

    Joined:
    Mar 18, 2014
    Posts:
    163
    Hi @yasirkula this asset is amazing- thanks so much!

    I'd like to be able to only show certain components, hiding all others, I'm hiding Transforms and Renderers etc using

    Code (CSharp):
    1. if( components[i] is Renderer )
    2.  
    3.     components.RemoveAt( i );
    Which works fine, but I'd also like to get rid of the Is Active, Name, Tag and Layer from all GameObjects- I've tried adding the above to a new InternalSettings-->HiddenVariables but can't seem to get rid of them... Can you help?
     
  49. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    2,879
    wxxhrt likes this.
  50. wxxhrt

    wxxhrt

    Joined:
    Mar 18, 2014
    Posts:
    163