I am writing a custom editor for one of my scripts. The script has private fields that I want to expose to the editor. I want to keep them private as I don’t want them to be able to be editable by other classes. I have used [SerializeField] to expose private variables in the standard editor, but I don’t know how to expose them in a custom editor.
Class:
public class Foo : MonoBehaviour
{
[SerializeField] private int bar;
}
CustomEditor:
[CustomEditor(typeof(Foo))]
public class EditorFoo : Editor
{
public override void OnInspectorGUI()
{
Foo script = (Foo)target;
script.bar = EditorGUILayout.IntField("Bar:" script.bar); // Bar is inaccessible due to its protection level
);
}
}
Use the SerializedObject / SerializedProperty mechanics instead of using the “target” field. This is the recommended solution
Add some sort of public property or getter / setter to your class so the editor can actually access it. This of course indirectly makes the field editable by others.
Another way would be to use reflection to edit the private member field.
If it’s important for you that the field should not be exposed (directly or indirectly) the second solution is out. If you insist in using the old way to write custom inspectors (using “target” or “targets”) the only way to change private or protected members is to use reflection.
However the recommended way would be to use the serializedObject of the Editor. You would use FindProperty to get a SerializedProperty back. This can be used to modify the serialized data of that field.
The SerializedObject / SerializedProperty is actually a wrapper for the serialized data that Unity’s serializer has stored on the native side. It’s also used by the default inspector. Always keep in mind that the SerializedObject and SerializedProperty do not actually work on the class instance, but directly on the serialized data. That’s why the usage might seem a bit strange at first glance.
You may want to have a closer look at the first example on the Editor page
Private members are accessible to other members of the same class, including inner classes.
using UnityEditor;
using UnityEngine;
public class Foo : MonoBehaviour
{
private int bar;
[CustomEditor(typeof(Foo))]
public class EditorFoo : Editor
{
public override void OnInspectorGUI()
{
var script = (Foo)target;
script.bar = EditorGUILayout.IntField("Bar:", script.bar);
}
}
}
Another hot tip is make the class partial so your editor script can be in a different file.
// in file named Foo.cs
public partial class Foo : MonoBehaviour
{
private int bar;
}
// in a different file name Foo.Editor.cs
public partial class Foo
{
[CustomEditor(typeof(Foo))]
public class FooEditor: Editor
{
public override void OnInspectorGUI()
{
var script = (Foo)target;
script.bar = EditorGUILayout.IntField("Bar:", script.bar);
}
}
}