Removing / modifying in Inspector a generic variable derived from a non-generic variable
I'm doing some tests using generic variables to pass on data, with the following structure:
A regular, non-generic base class (to be able to create arrays and lists of the variables.
Derived from that, a generic class (which is the base for the variables).
Finally, a type-specific class, derived from the generic, to assign values.
Checking on the current documentation, I understood that the only way to show these variables in the inspector was using the [SerializeReference] attribute. And it kind of works:
These variables use too much space on the screen, so I gave it a try to simplify it with a custom inspector. The following is the code I used, taking the hints from this post.
// Generic class where the drawing is defined
public class GVariablePropertyDrawer<T> : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
var indent = EditorGUI.indentLevel;
EditorGUI.indentLevel = 0;
var labelRect = new Rect(position.x, position.y, 38, position.height);
var nameRect = new Rect(position.x + 38, position.y, position.width / 2 - 40, position.height);
var valueRect = new Rect(position.x + position.width / 2, position.y, position.width / 2, position.height);
GUIContent myLabel = new GUIContent("Name:");
EditorGUI.LabelField(labelRect, myLabel);
EditorGUI.PropertyField(nameRect, property.FindPropertyRelative("variableName"), GUIContent.none);
EditorGUI.PropertyField(valueRect, property.FindPropertyRelative("DefaultValue"), GUIContent.none);
EditorGUI.indentLevel = indent;
EditorGUI.EndProperty();
}
}
// Class-bound types for the editor
[CustomPropertyDrawer(typeof(IntVariable))] public class GVariablePropertyDrawer_Int : GVariablePropertyDrawer<int> { }
[CustomPropertyDrawer(typeof(FloatVariable))] public class GVariablePropertyDrawer_Float : GVariablePropertyDrawer<float> { }
[CustomPropertyDrawer(typeof(BoolVariable))] public class GVariablePropertyDrawer_Bool : GVariablePropertyDrawer<bool> { }
[CustomPropertyDrawer(typeof(TransformVariable))] public class GVariablePropertyDrawer_Transform : GVariablePropertyDrawer<Transform> { }
[CustomPropertyDrawer(typeof(Vector2Variable))] public class GVariablePropertyDrawer_Vector2 : GVariablePropertyDrawer<Vector2> { }
[CustomPropertyDrawer(typeof(Vector3Variable))] public class GVariablePropertyDrawer_Vector3 : GVariablePropertyDrawer<Vector3> { }
[CustomPropertyDrawer(typeof(LayerMaskVariable))] public class GVariablePropertyDrawer_LayerMask : GVariablePropertyDrawer<LayerMask> { }
This is the new look:
Now, I think there is an improvement, but the top bar (where the origin of the class as a Base Class is hinted at -and in fact where the generic type can be chosen from) is still a big hit on readability, and I do not know how it could be possible to either remove it or modify it, so as to make it less intrusive.
Ideally, it would become a small tag to identify the variable type, maybe still fulfilling the function of "selector" for the derived type, placed where the "name" label currently is, so it can all fit within a single line.
Does anyone know if it can be done and how, or if it can't, why?
Thank you for your time and attention.
That top bar is not part of your property drawer. It's also not part of the default UnityEditor. Are you using some plugin or package to draw that list? Unity's included reorderable lists don't look like that, so maybe that's the code that is drawing that top bar. We need to see the code that draws the top bar in order to tell you how to change it. Can you share it?
On a separate note, you can save creating all those different property drawers by using:
[CustomPropertyDrawer(typeof(GBaseVariable), true)]
public class GVariablePropertyDrawer : PropertyDrawer
Or, if GBaseVariable is generic:
[CustomPropertyDrawer(typeof(GBaseVariable<>), true)]
public class GVariablePropertyDrawer : PropertyDrawer
Hello, and thank you for the advice! You were right: that top bar was created by the Odin Serializer plugin - and thankfully they have a quick way to hide it.
Answer by jamesbean · May 09, 2021 at 05:37 PM
As @oscarAbraham noted, that bar was not being generated by Unity. Turns out it was created by the Odin Serializer plugin - and thankfully there is a quick way to remove it using an attribute in the same plugin:
[Serializable]
[HideReferenceObjectPicker]
public abstract class Variable<T> : BaseVariable
// ...
With that, the selection bar is removed from the inspector.
I made another quick-and-dirty test to set up the name of the variable from the object type:
// ...
string varName = (typeof(T).ToString());
varName = varName.Substring(varName.LastIndexOf('.') + 1);
GUIContent myLabel = new GUIContent(varName);
// ...
And the result looks like this:
There's ways to make it prettier, but that's the answer I was looking for. Hopefully this will help someone else.