- Home /
Modifying default Inspector GUI creator
I script in C# and recently created a set of scripts that will expose the properties and fields of a class to the inspector. Works like a dream, but it's a bit annoying to copy paste a new custom script changing out only the class type each and every time. Using properties let's me limit impossible settings and makes everything a lot cleaner. Really for C# scripting there's never a reason I'd prefer the default exposure to my own implementation so was wondering if there was a way to override their implementation somehow?
I am not fully understanding you here. When you say that you have created a set of scripts that will expose the properties and fields of a class to the inspector, do you then mean that your fields are public, use the [SerializableField] attribute or that you have created your own custom inspector for your class Script? Also, to somewhat answer your question; the possibilities for creating inspector gui stuff is very limiting. It might help you that if you set your inspector to debug mode you can at least see the properties (but not modify them).
Skjalg is right. I think you need to provide some kind of example or what you are trying to achieve.
Sorry for not being clear.
I created a set of Attributes [ExposeProperty],[ExposeField],[ExposeClass]
If you use [ExposeProperty] it will display the a gui element based on the property it is assigned too. Ie. if it's a string create a textfield, int creates an intfield, so on and so forth. When it does this it uses the get/set method provided by your code. This lets you do some cool things with properties. Example, if you tried to set Health > $$anonymous$$axHealth a check in your property would make Health = $$anonymous$$axHealth, no way to accidently misassign values in your editor because the same checks that are applied to your property code in game are applied to the values passed to the editor. Since in C# you should be using properties for several values anyways this is really useful.
[ExposeField] is simply my methods attribute that will expose a field just like in Unity.
Finally [ExposeClass] is a method that will do [ExposeField],[ExposeProperty] for each public Property or Attribute.
So to implement this I need to create a custom editor for each class like so
[CustomEditor(typeof(HealingPotion))]
public class HealingPotionEditor : Editor
{
HealingPotion thing;
ExposeProperties.PropertyField[] properties;
public override void OnInspectorGUI()
{
if (thing == null)
return;
ExposeProperties.Expose(properties);
}
public void OnEnable()
{
thing = target as HealingPotion;
properties = ExposeProperties.GetProperties(thing);
}
}
The only way this code differentiates itself from each class is replacing HealingPotion with any other class.
So I was wondering if there was a way to override Unity to use a generic version of that code for every class I submit rather than having to copy/paste then refactor it everyt ime.
Answer by Rod-Green · Oct 31, 2011 at 11:46 PM
Im not sure you can create a generic implementation of the CustomEditor but you might be able to do something like :
public class MyBaseEditor<T> : Editor where T:MonoBehaviour
{
T thing;
ExposeProperties.PropertyField[] properties;
public override void OnInspectorGUI()
{
if (thing == null)
return;
ExposeProperties.Expose(properties);
}
public void OnEnable()
{
thing = target as T;
properties = ExposeProperties.GetProperties(thing);
}
}
then implement it each time like:
[CustomEditor(typeof(HealingPotion))]
public class HealingPotionEditor<HealingPotion> : MyBaseEditor {}
?? Untested ..
However are you sure you 'really' want to use a custom editor for this?
Why don't you just have an [ExecuteInEdit$$anonymous$$ode] flag on the base class and 'handle' the data as it's changed. Really CustomEditors seem to be designed when you want to represent the data on the class differently than you want to store it. I.e. store a dictionary of values but just show the total count.
How exactly does this work? [ExecuteinEditor] can't find info on this attribute.
Sorry should have been [ExecuteInEdit$$anonymous$$ode] http://unity3d.com/support/documentation/ScriptReference/ExecuteInEdit$$anonymous$$ode.html
I assume you mean this http://unity3d.com/support/documentation/ScriptReference/ExecuteInEdit$$anonymous$$ode.html
I could see how it would be useful, but not how I can apply it in this situation.
Well lets say you wanted to clamp a value i.e. health to be a max of 255 and a $$anonymous$$ of 0..
So as the user goes to edit the health and they type -100 the 'Update()' method will be called on the class even though the game isn't playing.
then you can do something like
void EditorUpdate()
{
health = $$anonymous$$athf.Clamp(health, 0, 255);
}
void Update()
{
#if UNITY_EDITOR
if(!Application.isPlaying)
EditorUpdate();
#endif
}
Be warned though that because the class is executing in edit mode it will trigger other methods (Awake, Start, OnGUI, OnEnable, OnDestory etc)..
But the power would be you could create one base class - "potion" and have all these methods only defined once.
Answer by HappyMoo · Dec 31, 2013 at 11:10 AM
Yes, that's possible. Have all you classes inherit from a base class, then do this:
[CustomEditor(typeof(MyBaseClass), true)]
The "true" tells Unity to also call the Editor for all child classes.
I've also looked into having properties exposed on the inspector. Does serialization work with your solution, e.g. Prefabs keep their Values?
I expose my private variables for the inspector and have the properties for the runtime, then I use a custom editor with child class support to call a method to let the classes know that values got updated when the inspector changes something, but actually having the inspector use the getter/setters would be of course much better - given that serialization still works. How did you solve that?
Custom inspectors are just GUI suggar, they don't change or influence the serialization system at all. You can show any GUI you like but the rules for serialization stays the same. If you want to have full encapsulation you should serialize your private variables by using [SerializeField, HideInInspector]
on them. Properties are never serialized by Unity, only variables.
Btw: the second parameter in the CustomEditor constructor is quite new, so your solution only works in the most recent Unity versions.
Yes, I know, but ChaseLewis built Editors that calls the getter/setter. But doing so, doesn't tell Unity that something changes - you need to use the SerializedProperty for that. Now I wonder how he does it. For a generic solution you could try to map your private [SerielizeField] members to the Property by Name, but it would be nicer if you wouldn't have to do this. $$anonymous$$aybe it is possible to override how a class serializes - then you wouldn't need the mapping, but just an Editor that knows how to show Properties and a custom serializing method.
Answer by ChaseLewis · Oct 31, 2011 at 11:42 PM
Sorry for not being clear.
I created a set of Attributes [ExposeProperty],[ExposeField],[ExposeClass]
If you use [ExposeProperty] it will display the a gui element based on the property it is assigned too. Ie. if it's a string create a textfield, int creates an intfield, so on and so forth. When it does this it uses the get/set method provided by your code. This lets you do some cool things with properties. Example, if you tried to set Health > MaxHealth a check in your property would make Health = MaxHealth, no way to accidently misassign values in your editor because the same checks that are applied to your property code in game are applied to the values passed to the editor. Since in C# you should be using properties for several values anyways this is really useful.
[ExposeField] is simply my methods attribute that will expose a field just like in Unity.
Finally [ExposeClass] is a method that will do [ExposeField],[ExposeProperty] for each public Property or Attribute.
So to implement this I need to create a custom editor for each class like so
[CustomEditor(typeof(SmallPotion))]
public class HealingPotionEditor : Editor
{
HealingPotion thing;
ExposeProperties.PropertyField[] properties;
public override void OnInspectorGUI()
{
//CharacterGUILayout(this,character);
if (thing == null)
return;
ExposeProperties.Expose(properties);
}
public void OnEnable()
{
thing = target as HealingPotion;
properties = ExposeProperties.GetProperties(thing);
}
}
The only way this code differentiates itself from each class is replacing HealingPotion with any other class.
So I was wondering if there was a way to override Unity to use a generic version of that code for every class I submit rather than having to copy/paste then refactor it everyt ime.
Delete this - it's not an answer. Add it to your original question.
It looks like to me that you are just one short step away from creating your very own inspector window. Why not go the extra mile and do just that?