Search Unity

Semi-automatic property inspector in-game?

Discussion in 'Immediate Mode GUI (IMGUI)' started by Sprocket, Sep 18, 2010.

  1. Sprocket

    Sprocket

    Joined:
    Sep 18, 2010
    Posts:
    31
    I am programming some small apps with algorithmic/simulated computer generated content. These are not games, but more like small sandboxes to play around with. For an example of this you can check out this prototype: http://emerganz.com/LorentzTrails.html

    Each scene will have a number of configurable parameters. These are easy to tweak in the editor (via the Inspector), but I would like for them to be tweakable in the final build as well. Since I'll be doing a lot of scenes I'm wondering if its possible to automate (or semi-automate) this process.

    To be specific: a GUI script that takes another script as a parameter and looks throgh that script for public variables which is then represented with appropriate GUI controls (sliders, drop-down, checkmarks etc.). Using the GUI controls then changes the parameters of the script.

    Alternatively to looking through all public variables it could also require a certain data structure to be present (ala a struct) which is then parsed by the GUI script.

    Preferably this would make the variables accessible both inside the game and from the editor's inspector, however this is not an absolute requirement.

    My question is what is the best way to implement this? I am fairly new to both javascript and C#, so I'm not familiar with their introspection features.

    Any help will be appreciated. :)
     
  2. Jesse Anders

    Jesse Anders

    Joined:
    Apr 5, 2008
    Posts:
    2,857
    I recently posted a somewhat speculative reply to a thread, and then was embarrassed when someone else posted a much better answer. This answer is speculative as well, and maybe the same thing will happen here - I suppose we'll see.

    Anyway, I believe this can be done using reflection. I put together the following quick test code in C#:

    InspectorTarget.cs:

    Code (csharp):
    1. using UnityEngine;
    2.  
    3. public class InspectorTarget : MonoBehaviour
    4. {
    5.     public float field1;
    6.     public string field2;
    7. }
    Inspector.cs:

    Code (csharp):
    1. using System;
    2. using System.Reflection;
    3. using UnityEngine;
    4.  
    5. public class Inspector : MonoBehaviour
    6. {
    7.     public InspectorTarget target;
    8.  
    9.     void OnGUI()
    10.     {
    11.         Type type = typeof(InspectorTarget);
    12.         FieldInfo[] fields = type.GetFields();
    13.         foreach (FieldInfo field in fields) {
    14.             if (field.FieldType == typeof(float)) {
    15.                 field.SetValue(
    16.                     target,
    17.                     GUILayout.HorizontalSlider(
    18.                         (float)field.GetValue(target),
    19.                         0f,
    20.                         1f,
    21.                         GUILayout.Width(100f)
    22.                     )
    23.                 );
    24.             } else if (field.FieldType == typeof(string)) {
    25.                 field.SetValue(
    26.                     target,
    27.                     GUILayout.TextField(
    28.                         (string)field.GetValue(target),
    29.                         GUILayout.Width(100f)
    30.                     )
    31.                 );
    32.             }
    33.         }
    34.     }
    35. }
    36.  
    And this worked as expected. Note that when running in the editor, the values set while in 'play mode' will not be preserved once you've returned to edit mode (which is the same behavior you see when modifying values in the Unity inspector while in play mode). If you want the values to be saved (either to the scene, or between runs of a standalone app), you'd have to take some extra steps to make that happen.

    Also, the above code is of course type-specific; I didn't bother trying to figure it out for this brief example, but I imagine reflection could be used to make the inspector work with an arbitrary type instead.

    Again, this is speculative, and there may be some problem, issue, or better solution that I'm overlooking. But, for what it's worth, the above code does seem to produce the desired behavior in my test project.

    (Btw, very cool demo.)
     
    look001 likes this.
  3. look001

    look001

    Joined:
    Mar 23, 2017
    Posts:
    111
    Thank you so much! reflection is awesome realy appreciate it! Thanks for the tip
     
    Last edited: Aug 6, 2018