Search Unity

  1. Unity 2019.1 is now released.
    Dismiss Notice

Runtime Inspector and Hierarchy [Open Source]

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

  1. CabbageCrow

    CabbageCrow

    Joined:
    May 28, 2017
    Posts:
    4
    I'm making good progress injecting the Runtime Inspector. :)
    I'm implementing and thinking about additional features, like obviously selecting a GameObject when you click on it and highlighting it.

    Regarding the inspector itself it would be nice if there was a filter and/or highlight option. Like a placeable search field to search for all hierarchy elements which contains the string in their name.
    Then it either just highlights the objects and the parents (in a different color) if they are collapsed. There could be an option to uncollapse them too.
    Or it filters out all other elements except for the found objects (and maybe the currently selected one).

    How does that sound like? Is that something you would add in the future?
     
  2. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    915
    It is possible but not easy because:

    1- Each GameObject in the scene must be checked one-by-one to see if it matches the search
    2- The .name property of GameObject results in unavoidable GC
    3- Hierarchy must refresh itself frequently to see if any new object matches the search or if a previously matching object is now destroy/renamed

    Honestly, I don't plan to implement this feature for now :D
     
  3. CabbageCrow

    CabbageCrow

    Joined:
    May 28, 2017
    Posts:
    4
    Regarding the refreshing and GC you have already implemented the refresh interval and Object names refresh interval.

    I only skimmed the code a bit, but don't you have the scene saved in some form? And you need all the names for the hierarchy already? (At least for everything that is extended.)
    Correct me my train of thought, but where is the big overhead in looking through (the data of) the hierarchy inspector? Or is it not saved but only pulled and discarded when everything is built?
     
  4. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    915
    Yes, I don't cache the names of the objects. I pull and discard them at every object names refresh interval. Objects that are not visible in the RuntimeHierarchy are not referenced anywhere either, so I have to traverse all objects using transform.GetChild (probably recursively).
     
  5. CabbageCrow

    CabbageCrow

    Joined:
    May 28, 2017
    Posts:
    4
    I guess with short update intervals or even every frame there is no use in caching them.
    Makes sense you only access only the stuff you have to. I mean all the garbage isn't good, but if the user needs it, well ... Yet that means no live searching while typing, only on Enter/Button-click.
    Also disabling the auto-refresh completely when it shows a filtered result? Otherwise it would do it in the worst case on every frame. (A manual refresh button would be nice either way)

    GameObject.Find() doesn't work, since it only looks for the whole name, no substrings.
    Regarding the recursion: Not necessary. Just using Object.FindObjectsOfType(typeof(GameObject)) would return all of them.

    Where exactly would you have to intercept to show only a certain set of elements in the hierarchy?

    A completely different question: How can you adjust the "label to input fields"-ratio of the Inspector?
    (Furthermore - Is there a horizontal Scrollbar?)

    upload_2019-1-18_21-13-38.png
     
  6. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    915
    I'd create a separate ScrollView inside RuntimeHierarchy and list the results there. While the search results are listed, I'd deactivate the original ScrollView object to save some draw calls. You can let RuntimeHierarchy keep doing its job even while the search results are listed. So, your code should only be responsible for switching between ScrollView objects and listing the search results inside its corresponding ScrollView.

    At the moment, the label-to-input-fields ratio is not set programmatically, these placements are done by hand for each prefab inside Prefabs-RuntimeInspector-Fields.

    Adding a horizontal scrollbar to either of the panels won't work out-of-the-box, I've tried it before with RuntimeHierarchy and it required some refactoring both in some prefabs and in the code: https://forum.unity.com/threads/runtime-inspector-and-hierarchy-open-source.501220/#post-3477214
     
  7. Diego_Graphics

    Diego_Graphics

    Joined:
    Nov 3, 2014
    Posts:
    81
    Is there a way to restrict the runtime hierarchy to a specific root object so that only child objects are displayed? an optional transform target would be cool.
     
  8. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    915
    You can disable RuntimeHierarchy's "Expose Unity Scenes" property and attach a "Pseudo Scene Source Transform" component to the root object.
     
  9. Diego_Graphics

    Diego_Graphics

    Joined:
    Nov 3, 2014
    Posts:
    81
    Oh, that's exactly what I was looking for. Thank you very much !
     
    yasirkula likes this.
  10. charlie_sbg

    charlie_sbg

    Joined:
    Dec 18, 2016
    Posts:
    9
    We just updated to Unity 2018.3 (from Unity 5.6). When we show a long list in the inspector it was scrolling on device before but now it does not. Any ideas?

    Thanks! Very cool tool!
     
  11. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    915
    I've tried to reproduce this issue on Unity 2018.3.3f1 but everything worked correctly for me. Are there any retro steps that I can follow?
     
  12. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    915
    @CabbageCrow After a while, I've added a searchbar to the RuntimeHierarchy. If you are interested, you can import the attached unitypackage to your project. I'll be updating the GitHub repo and the Asset Store version soon.

    HierarchySearch.png

    P.S. New version is now live on Asset Store.
     

    Attached Files:

    Last edited: Feb 21, 2019
  13. charlie_sbg

    charlie_sbg

    Joined:
    Dec 18, 2016
    Posts:
    9
    Thanks for getting back. I don't know what retro steps to show. I hate to throw this back, but do you have a top list of expected issues? A few gotchas we can try?

    * We can scroll with a mouse (and scroll wheel) in the editor AND in android (with a mouse connected)
    * We can not scroll with touch on device. But we can click on elements.
    * We mostly use NGUI (older project) so perhaps we don't have something set just right on a camera or something.
    * We have about 6 cameras, sometimes 3 or 4 are active :(
     
  14. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    915
    I've tested my project (built with 2018.3.3f1) on S8 and again, it worked without any issues.

    You can try deleting the EventSystem object and creating it anew via the GameObject-UI menu. If you are using World Space UI, try assigning an Event Camera to the Canvas.

    Other than that, I don't have any other possible fixes in mind. Does this issue also occur on a fresh project (if it does, try using a different Unity version)? I don't think NGUI or some wrong camera parameters can cause this issue but I can't say for certain.
     
  15. charlie_sbg

    charlie_sbg

    Joined:
    Dec 18, 2016
    Posts:
    9
    Thank you for your time. I don't expect this is a runtime inspector bug so I'm not going to spam this thread. I'm sure we are doing something weird. :p But I tried the things you mentioned without luck so far. Thanks again!
     
    yasirkula likes this.
  16. StarCoop

    StarCoop

    Joined:
    Nov 26, 2016
    Posts:
    15
    Hi there,

    I'd have a request for the asset: Would it be possible to add multiselection via CTRL+Select and SHIFT+Select (like in a regular folder)? I would try to do it myself, but I needed to dive into the selection logic and probably break a lot of things up at first.
    I already changed some scripts to fit to our needs, but this one is a bigger part I think.
    Also, do you see any possiblity to speed the scrollview up? It is a NGUI issue I think due to the slow layouting system, but when I expand an item containing 1000+ children, the loading of the list takes quite long, and we have many of them ^^.
     
  17. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    915
    Hi, why would you want to select multiple objects in the hierarchy?

    The performance issue is most probably related to instantiating that many objects at each expand. You may increase the pool size of RuntimeHierarchy to possibly reduce the lag in consequent expands.
     
  18. StarCoop

    StarCoop

    Joined:
    Nov 26, 2016
    Posts:
    15
    This is actually one of the most important features for us ^^. We're using your tool as a viewer for CAD part lists, where each CAD part and its hierarchy are instantiated as GameObjects that are shown by your runtime hierarchy. As we want to select groups of objects from this list, we would need the multiselect. Your tool is not only for referencing the scene hierarchy in runtime, but for easy and powerful creation of tree views!

    I noticed that when an element on, say, level 4 (so 4 expand arrows later) has been expanded, also other elements up to this level get expanded quite faster, independent of their number. Could you confirm this behaviour? Would there be a workaround to auto-expand single items up to a certain level in order to make other elements expand faster?
     
  19. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    915
    I'll try to use a recycled list view in order not to Instantiate any hierarchy items for the invisible transforms in the hierarchy. This should resolve the second issue.

    The first one will require changing RuntimeHierarchy.CurrentSelection, RuntimeHierarchy.Select and RuntimeHierarchy.Deselect. I might work on this, as well but I'm making no promises for this.
     
  20. DewiMorgan

    DewiMorgan

    Joined:
    May 20, 2018
    Posts:
    5
    @CabbageCrow that Harmony integration sounds really awesome - could you explain how you accomplished it? Is there source code of your solution I could check out?
     
  21. DewiMorgan

    DewiMorgan

    Joined:
    May 20, 2018
    Posts:
    5
    @yasirkula Sorry for what is probably a very newbie question, but how can I programmatically cause it to appear? I see comments like "just bind it to a button"... but if I want something in C# to make, say, the Hierarchy or Inspector to appear, what do I call?
     
  22. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    915
    Create a
    public GameObject hierarchy;
    variable and call
    hierarchy.SetActive(true);
    to show it,
    hierarchy.SetActive(false);
    to hide it. You need to assign the RuntimeHierarchy object in your scene to the Hierarchy variable.
     
  23. DewiMorgan

    DewiMorgan

    Joined:
    May 20, 2018
    Posts:
    5
    Ah, so you need to create a GameObject, then "assign" the RuntimeHierarchy/RuntimeInspector objects to those. I'm afraid I don't really know what "assign" means in C#/Unity terms, however.

    You say it like it's simple, so I am sure I am just being stupid here, but I've now spent five hours on it, and have run out of ideas.

    Here's as close as I can get to a minimal test-case mod (yeah, using your namespace to save a single `using` line is probably overdoing "minimal test case", I know...).

    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityModManagerNet;
    4.  
    5. namespace RuntimeInspectorNamespace
    6. {
    7.     static class Main
    8.     {
    9.         public static GameObject runtimeHierarchy;
    10.         public static GameObject runtimeInspector;
    11.  
    12.         static bool Load(UnityModManager.ModEntry modEntry)
    13.         {
    14.             modEntry.OnGUI = OnGUI;
    15.             return true;
    16.         }
    17.  
    18.         static void OnGUI(UnityModManager.ModEntry modEntry)
    19.         {
    20.             if (GUILayout.Button("Runtime Awesomeness")) {
    21.                 SpawnRuntimeAwesomeness();
    22.             }
    23.         }
    24.  
    25.         public static void SpawnRuntimeAwesomeness()
    26.         {
    27.             if (!Main.runtimeHierarchy) {
    28.                 Main.runtimeHierarchy = new GameObject("Hierarchy");
    29.             }
    30.             if (!Main.runtimeInspector) {
    31.                 Main.runtimeInspector = new GameObject("Inspector");
    32.             }
    33.             // At this point, Main.runtimeHierarchy.active=true, .activeInHierarchy=true, .activeSelf=true.
    34.  
    35.             Main.runtimeHierarchy.AddComponent<RuntimeHierarchy>();
    36.             Main.runtimeInspector.AddComponent<RuntimeInspector>();
    37.             RuntimeHierarchy rh = Main.runtimeHierarchy.GetComponent<RuntimeHierarchy>();
    38.             RuntimeInspector ri = Main.runtimeInspector.GetComponent<RuntimeInspector>();
    39.             // At this point, rh.enabled=false, rh.isActiveAndEnabled=false, rh.ConnectedInspector=null
    40.  
    41.             rh.ConnectedInspector = ri;
    42.             ri.ConnectedHierarchy = rh;
    43.             // At this point, rh.ConnectedInspector=ri
    44.  
    45.             //ri.Inspect(Main.runtimeHierarchy);
    46.             // Above throws an null pointer exception.
    47.  
    48.             Main.runtimeHierarchy.SetActive(true);
    49.             Main.runtimeInspector.SetActive(true);
    50.             // At this point, Main.runtimeHierarchy.active=true, .activeInHierarchy=true, .activeSelf=true,
    51.             // rh.enabled=false, rh.isActiveAndEnabled=false, rh.ConnectedInspector=ri
    52.             // (ie, none of the above have changed).
    53.  
    54.             rh.enabled = true;
    55.             ri.enabled = true;
    56.             // At this point rh.enabled=true, rh.isActiveAndEnabled=true, but it still doesn't show.
    57.         }
    58.     }
    59. }
    60.  
     
    Last edited: Apr 27, 2019
  24. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    915
    You need not overcomplicate things. In the Editor, simply drag&drop RuntimeInspector and RuntimeHierarchy prefabs to your canvas (make sure that you can see them in the Scene view), deactivate them from the Inspector (the checkbox next to the object's name) and then assign them to public variables from the Inspector. You can then simply activate them from your code.

    If you really need to create these objects by code, have a reference to their prefabs in your code (or move these prefabs to Resources folder and call Resources.Load to access them) and Instantiate them inside your canvas instead of
    new GameObject
    . You will then need to position them by code, as well.
     
  25. DewiMorgan

    DewiMorgan

    Joined:
    May 20, 2018
    Posts:
    5
    I get that this would be trivial in the editor, but unfortunately, I do need to do this programmatically. Like @CabbageCrow, I am using Harmony to hook an existing executable (harmony code was not used in my minimal example, for simplicity), and am compiling a DLL that gets linked in with the game, so sadly, the unity editor, with its concepts of "drag and drop", the "resources folder", and so forth are not features that I have access to.

    That's not overcomplicating things - it's just the constraints within which I am working, at least as I understand them.

    I don't think I can refer to a "prefab", either: I have your code compiled into a DLL (per https://docs.unity3d.com/Manual/UsingDLL.html), and all I can see are classes and their methods. Unity code prefabs aren't a thing in DLLs.

    Sadly, while this is apparently a solved problem for CabbageCow, they have not signed in lately, so the solution they found can only remain a mystery :)
     
    Last edited: Apr 27, 2019
  26. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    915
    As far as I understand, you have access to the C# scripts only and no prefabs or whatsoever. In this case, you can't really use this plugin because it uses tons of prefabs, sprites, shaders and scriptable objects. You can't create these assets manually by code, it would be extremely tedious. You'd have to create each prefab manually by code, you can guess how complex it would make things. I think the only viable option with Harmony's requirements would be to use a solution that completely relies on OnGUI.
     
  27. DewiMorgan

    DewiMorgan

    Joined:
    May 20, 2018
    Posts:
    5
    Hrm. That's unfortunate, but valuable to know - thank you.

    But I'm not ready to give up on your work yet. I *can* load in assets from assetbundles. There's a command
    assetBundle.LoadAsset<GameObject>("assets/containers/prefabs/prefabName.prefab");
    ... but you can't put scripts into assetbundles, you have to put them into DLLs: but I've done that already, so what's left is just a Small Matter of Programming. That, and figuring out what the heck to program, of course.

    It looks like @CabbageCrow was able to make it work somehow, which does give me hope. I think (for the modding community of the game, if nothing else) it'd be worthwhile me having a bash at it. If I do find a way, I'll post it here as it's the most likely place to be useful to others.

    If I find that it's possible to make changes to your system to allow purely-code-based usage, without affecting the more common use-case, would you be interested in these changes as a pull requests to your repo?

    And if, as now seems plausible, I actually do need to roll my own separate mechanism from scratch, would you be OK with me using your work as a base? (other than the color wheel, which I see you've flagged as a separately licensed thing). What license should I use for your work, if so?
     
  28. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    915
    Good luck with your solution, I really wish that you succeed. I'd need to review your pull request before merging it but a purely-code-based method is surely welcome :)

    You can definitely use my plugin as a base in your final product; if you plan to publish it on GitHub, please take the MIT License of RuntimeInspector into account. On Asset Store, you don't need to mention the MIT License because the Asset Store version of RuntimeInspector is licensed under the Asset Store EULA.
     
  29. charles_meng

    charles_meng

    Joined:
    Apr 17, 2019
    Posts:
    1
    Hi there,
    The asset is awesome and useful.However, I do have an issue I can't solve myself.
    How could I just show some of the transforms and hide the others in HierarchyItemRoot?

    Could you help me?
    Thanks in advance!
     
  30. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    915
  31. jbergs

    jbergs

    Joined:
    Feb 13, 2014
    Posts:
    8
    I may have missed something in reading the docs, so I apologize if I have. Is there a way to hide specific custom scripts that have been assigned to my gameobjects so they're hidden in the Inspector?
     
  32. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    915
  33. jbergs

    jbergs

    Joined:
    Feb 13, 2014
    Posts:
    8
    Thanks, I did try that the other day and wasn't successful. I was able to get the other Components removed that I didn't need using this:

    Code (CSharp):
    1. if( components[i] is Renderer || components[i] is Collider || components[i] is MeshFilter || components[i] is Animator || components[i] is ThisPrefab)
    2.       components.RemoveAt( i );
    It's that last one that is having the issue. It's a custom script I made that's attached to the gameobject called "ThisPrefab.cs". It still shows up.

    I even tried:
    Code (CSharp):
    1. components[i].name == "ThisPrefab"
    Maybe I need to have it as part as a namespace.. Any thoughts? Awesome Asset btw!
     
  34. yasirkula

    yasirkula

    Joined:
    Aug 1, 2011
    Posts:
    915
    If the attached script's class is named ThisPrefab, then it is supposed to work. For testing purposes, you can Debug.Log all the components in GameObjectField to see the component's type.
     
  35. jbergs

    jbergs

    Joined:
    Feb 13, 2014
    Posts:
    8
    Thank you. I was having trouble printing to the console the names of each component because 'components.name'. would just print the GameObjects name (I'm learning). So I don't know whether it's the best way, but I got it to work using this:
    Code (CSharp):
    1.  if(components[i].GetNameWithType().Contains("ThisPrefab"))
    2.       {
    3.           components.RemoveAt( i );
    4.       }
    Thank you for your help!
     
    Last edited: May 22, 2019