Skip to content

Instantly share code, notes, and snippets.

@blurrryy
Forked from douduck08/README.md
Created October 20, 2022 23:51
Show Gist options
  • Save blurrryy/764f82c3c4663012bf1518e49175c99e to your computer and use it in GitHub Desktop.
Save blurrryy/764f82c3c4663012bf1518e49175c99e to your computer and use it in GitHub Desktop.
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;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment