Skip to content

Instantly share code, notes, and snippets.

@fuqunaga
Last active August 8, 2024 01:59
Show Gist options
  • Save fuqunaga/32f0ceeded671f6bdcace71e3214d993 to your computer and use it in GitHub Desktop.
Save fuqunaga/32f0ceeded671f6bdcace71e3214d993 to your computer and use it in GitHub Desktop.
Get actual object of SerializedProperty
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;
using UnityEngine.Assertions;
public static class SerializedPropertyExtensions
{
private static readonly Dictionary<(Type, string fieldName), FieldInfo> _fieldInfoDictionary = new();
private static readonly Regex ArrayDataRegex = new(@"data\[(\d+)\]");
public static object GetActualObject(this SerializedProperty property)
{
var serializedObject = property.serializedObject;
if (serializedObject == null)
{
return null;
}
object targetObject = serializedObject.targetObject;
foreach (var fieldName in property.propertyPath.Split('.'))
{
if (targetObject == null)
{
break;
}
var type = targetObject.GetType();
// Array/ListのpropertyPathは
// "Array.data[n]" となっている
if (targetObject is IList list)
{
if (fieldName == "Array")
{
continue;
}
var match = ArrayDataRegex.Match(fieldName);
if (!match.Success)
{
Debug.LogWarning($"Invalid propertyPath: {property.propertyPath}");
return null;
}
var index = Convert.ToInt32(match.Groups[1].Value);
targetObject = list[index];
continue;
}
var key = (type, fieldName);
if (!_fieldInfoDictionary.TryGetValue(key, out var fi))
{
fi = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
_fieldInfoDictionary[key] = fi;
Assert.IsNotNull(fi, $"FieldInfo is null. Type: {type}, FieldName: {fieldName}");
}
targetObject = fi.GetValue(targetObject);
}
return targetObject;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment