- Home /
Question by
Bypab212 · Nov 16, 2020 at 06:46 PM ·
unityeditorreflection
Is it possible to access a field from an editor without making it public?
It occurred to me to use reflection to access private fields and be able to modify them from the inspector or even from the editor script. But when I switch between scenes or open and close unity the values disappear.
These are the scripts that I have used for testing. Player Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour {
private string playerName = "Some Name";
private int health = 100;
private int xp = 75;
private string[] items = new string[] { "Sword", "Shield" };
public bool IsDead { get { return health <= 0; } }
public int Level { get { return xp / 100; } }
public void Heal(int heal) {
health += heal;
}
public void Damage(int damage) {
health -= damage;
}
public void AddXP(int xp) {
this.xp += xp;
}
}
Field
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
public class Field<T> {
private Component component;
private FieldInfo fieldInfo;
public Field(string fieldName, Component component) {
if (string.IsNullOrEmpty(fieldName))
throw new System.ArgumentException("Field name cannot be Null or Empty.");
this.component = component;
fieldInfo = component.GetType().GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
}
public T GetValue() {
return (T)fieldInfo.GetValue(component);
}
public void SetValue(T value) {
fieldInfo.SetValue(component, value);
}
}
PlayerEditor
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(Player))]
public class PlayerEditor : Editor {
private int heal = 0;
private int damage = 0;
private int xp = 0;
private int length;
public override void OnInspectorGUI() {
Draw();
}
private void Draw() {
Player player = (Player)target;
// Fields.
Field<string> nameField = new Field<string>("playerName", player);
nameField.SetValue(EditorGUILayout.TextField("Name", nameField.GetValue()));
EditorGUILayout.LabelField("Dead", player.IsDead.ToString());
Field<int> healthField = new Field<int>("health", player);
healthField.SetValue(EditorGUILayout.IntField("Health", healthField.GetValue()));
EditorGUILayout.LabelField("Level", player.Level.ToString());
Field<int> xpField = new Field<int>("xp", player);
xpField.SetValue(EditorGUILayout.IntField("XP", xpField.GetValue()));
EditorGUILayout.BeginHorizontal();
// Display Items array.
Field<string[]> itemsField = new Field<string[]>("items", player);
length = EditorGUILayout.IntSlider("Items", length, 0, 4);
if (GUILayout.Button("Update Items"))
itemsField.SetValue(new string[length]);
EditorGUILayout.EndHorizontal();
for (int i = 0; i < itemsField.GetValue().Length; i++) {
itemsField.GetValue()[i] = EditorGUILayout.TextField($"Item {i}", itemsField.GetValue()[i]);
}
// Buttons.
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
heal = EditorGUILayout.IntField(heal);
if (GUILayout.Button("Heal"))
player.Heal(heal);
damage = EditorGUILayout.IntField(damage);
if (GUILayout.Button("Damage"))
player.Damage(damage);
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
xp = EditorGUILayout.IntField(xp);
if (GUILayout.Button("Add XP"))
player.AddXP(xp);
EditorGUILayout.EndHorizontal();
}
}
Comment
Best Answer
Answer by myzzie · Nov 16, 2020 at 07:03 PM
Unity already handles it for you!
public class Example : MonoBehaviour
{
[SerializeField] private float myFloat;
}
[CustomEditor(typeof(Example))]
public class ExampleEditor : Editor
{
public override void OnInspectorGUI()
{
serializedObject.Update();
var myFloatProperty = serializedObject.FindProperty("myFloat");
EditorGUILayout.PropertyField(myFloatProperty);
serializedObject.ApplyModifiedProperties();
}
}