- Home /
How to change inspector with non-Monobehaviour objects ?
Hi there,
I have tried for a while now to make a custom inspector for different possible actions in my game.
This is my inspector for a Unit script having a bunch of attributes and methods.
But I'm interested in the public List<Action> Actions
attribute it has. I would like to change the inspector in each element of this list depending on what "Effect" (a public enum ActionEffects
) is selected, so that each element would look something like this:
The problem is that my Action class does NOT inherit from MonoBehaviour, as it is just a generic class, and my custom inspector script only changes MonoBehaviour objects. Here is my custom inspector script:
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(Action)), CanEditMultipleObjects]
public class ActionsEditor : Editor {
public SerializedProperty enum_Prop, prop_1, prop_2, ... // List of the properties
private void OnEnable() {
enum_Prop = serializedObject.FindProperty("effect");
prop_1 = serializedObject.FindProperty("prop1");
prop_2 = serializedObject.FindProperty("prop2");
// Etc.
}
public override void OnInspectorGUI () {
serializedObject.Update();
EditorGUILayout.PropertyField(enum_Prop);
ActionEffects effect = (ActionEffects)effect_Prop.enumValueIndex;
switch (effect) {
case ActionEffects.Movement:
// Display the relevant properties.
break;
case ActionEffects.SimpleDamage:
// Display the relevant properties.
break;
case ActionEffects.PushSingleTarget:
// Display the relevant properties.
break;
}
serializedObject.ApplyModifiedProperties();
}
}
And my Action script looks like this:
using UnityEngine;
public enum ActionEffects { Movement, SimpleDamage, PushSingleTarget}
[System.Serializable()]
public class Action {
public ActionEffects effect;
public string actionName;
// Other properties
// Some methods
}
I tried changing the Unit's inspector, but I can manage to change the Action part because I don't know how to access the attributes of the Action (I can't retrieve it's value as it is a custom class and not a default class such as string
, int
, float
, etc).
Is there a way to solve this ?
This is THE question! I also want to customize my editor in exactly the same way you want to customize yours - hide and show certain properties based on an enumerated type. Unfortunately, the only way I know how to do this so far is to customize the editor for a $$anonymous$$onoBehaviour script and accept an object of that script as a drop target in the "important" script
Answer by WarmedxMints · Sep 26, 2019 at 06:48 AM
You would need to create a property drawer for the class. Although I suggest renaming it as there is already an Action class in the System namespace.
MyAction.cs
public enum ActionEffects { Movement, SimpleDamage, PushSingleTarget }
[System.Serializable]
public class MyAction
{
public ActionEffects Effect;
public string ActionName;
}
MyActionPropertyDrawer.cs
using UnityEditor;
using UnityEngine;
[CustomPropertyDrawer(typeof(MyAction))]
public class MyActionPropertyDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
var indent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
var effectRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);
var secondRect = new Rect(position.x, position.y + 20f, position.width, EditorGUIUtility.singleLineHeight);
var effect = property.FindPropertyRelative("Effect");
var name = property.FindPropertyRelative("ActionName");
effect.intValue = EditorGUI.Popup(effectRect, "Effect", effect.intValue, effect.enumNames);
switch ((ActionEffects)effect.intValue)
{
case ActionEffects.Movement:
name.stringValue = EditorGUI.TextField(secondRect, "Action Name",name.stringValue);
//Anything else you want to display
break;
case ActionEffects.SimpleDamage:
name.stringValue = EditorGUI.TextField(secondRect, "Action Name", name.stringValue);
//Anything else you want to display
break;
case ActionEffects.PushSingleTarget:
name.stringValue = EditorGUI.TextField(secondRect, "Action Name", name.stringValue);
//Anything else you want to display
break;
}
EditorGUI.indentLevel = indent;
EditorGUI.EndProperty();
}
//This will need to be adjusted based on what you are displaying
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return (20 - EditorGUIUtility.singleLineHeight) + (EditorGUIUtility.singleLineHeight * 2);
}
}
Your answer
Follow this Question
Related Questions
Unity Editor - Class variable value contrain 4 Answers
Insert new custom class element with _default_ values to a SerializedProperty array? 1 Answer
Unity Custom Editor Texture Warning 2 Answers
Custom Inspector: Using SeralizedProperty changes the prefab values! 0 Answers
What should be handled in the custom inspector version of a script? 1 Answer