Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
The general GetValue extension of SerializedProperty in Unity Editor.

Unity's SerializedProperty not support custom type value setting. This extension use Reflection to get target instance of SerializedProperty in Custom Editor, made value setting of general type is posible.

// <author>
// douduck08: https://github.com/douduck08
// Use Reflection to get instance of Unity's SerializedProperty in Custom Editor.
// Modified codes from 'Unity Answers', in order to apply on nested List<T> or Array.
//
// Original author: HiddenMonk & Johannes Deml
// Ref: http://answers.unity3d.com/questions/627090/convert-serializedproperty-to-custom-class.html
// </author>
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
public static class SerializedPropertyExtensions {
public static T GetValue<T> (this SerializedProperty property) where T : class {
object obj = property.serializedObject.targetObject;
string path = property.propertyPath.Replace (".Array.data", "");
string[] fieldStructure = path.Split ('.');
Regex rgx = new Regex (@"\[\d+\]");
for (int i = 0; i < fieldStructure.Length; i++) {
if (fieldStructure[i].Contains ("[")) {
int index = System.Convert.ToInt32 (new string (fieldStructure[i].Where (c => char.IsDigit (c)).ToArray ()));
obj = GetFieldValueWithIndex (rgx.Replace (fieldStructure[i], ""), obj, index);
} else {
obj = GetFieldValue (fieldStructure[i], obj);
}
}
return (T) obj;
}
public static bool SetValue<T> (this SerializedProperty property, T value) where T : class {
object obj = property.serializedObject.targetObject;
string path = property.propertyPath.Replace (".Array.data", "");
string[] fieldStructure = path.Split ('.');
Regex rgx = new Regex (@"\[\d+\]");
for (int i = 0; i < fieldStructure.Length - 1; i++) {
if (fieldStructure[i].Contains ("[")) {
int index = System.Convert.ToInt32 (new string (fieldStructure[i].Where (c => char.IsDigit (c)).ToArray ()));
obj = GetFieldValueWithIndex (rgx.Replace (fieldStructure[i], ""), obj, index);
} else {
obj = GetFieldValue (fieldStructure[i], obj);
}
}
string fieldName = fieldStructure.Last ();
if (fieldName.Contains ("[")) {
int index = System.Convert.ToInt32 (new string (fieldName.Where (c => char.IsDigit (c)).ToArray ()));
return SetFieldValueWithIndex (rgx.Replace (fieldName, ""), obj, index, value);
} else {
Debug.Log(value);
return SetFieldValue (fieldName, obj, value);
}
}
private static object GetFieldValue (string fieldName, object obj, BindingFlags bindings = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) {
FieldInfo field = obj.GetType ().GetField (fieldName, bindings);
if (field != null) {
return field.GetValue (obj);
}
return default (object);
}
private static object GetFieldValueWithIndex (string fieldName, object obj, int index, BindingFlags bindings = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) {
FieldInfo field = obj.GetType ().GetField (fieldName, bindings);
if (field != null) {
object list = field.GetValue (obj);
if (list.GetType ().IsArray) {
return ((object[]) list)[index];
} else if (list is IEnumerable) {
return ((IList) list)[index];
}
}
return default (object);
}
public static bool SetFieldValue (string fieldName, object obj, object value, bool includeAllBases = false, BindingFlags bindings = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) {
FieldInfo field = obj.GetType ().GetField (fieldName, bindings);
if (field != null) {
field.SetValue (obj, value);
return true;
}
return false;
}
public static bool SetFieldValueWithIndex (string fieldName, object obj, int index, object value, bool includeAllBases = false, BindingFlags bindings = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) {
FieldInfo field = obj.GetType ().GetField (fieldName, bindings);
if (field != null) {
object list = field.GetValue (obj);
if (list.GetType ().IsArray) {
((object[]) list)[index] = value;
return true;
} else if (value is IEnumerable) {
((IList) list)[index] = value;
return true;
}
}
return false;
}
}
@tkotha
Copy link

tkotha commented Nov 28, 2018

I love you for writing this

@yuhuihu
Copy link

yuhuihu commented Oct 22, 2021

I love you for writing this

👍

@Pete-morales
Copy link

Pete-morales commented Jan 28, 2022

You're a fucking star, and you just earned one too

@gislerro
Copy link

gislerro commented Apr 3, 2022

super useful! thanks alot for sharing this

@WillYuum
Copy link

WillYuum commented May 28, 2022

Than you for sharing epic content!

@knl97vladimir
Copy link

knl97vladimir commented Oct 3, 2022

Very useful script! Thank you very much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment