Trying to Invoke a method just by changing a field in the inspector

So in my game there is a non_monobehaviour class “Effect” that hold info about the effect that will be applied to the player. As the title says, I want to call a method in this class which does some changes to it, like updating the values in the description etc.
there is a way around it, which is to use OnValidate() in the Monobehaviour that contain this class as a field. this works as intended but i will have to implement it in every Monobehaviour script that has an effect class. after doing some research, i came with this solution, the only problem is; i get a copy of the object of the SerializedProperty instead of a reference. i get no error, and after debugging, it does the job, but only changes the “copy” instead of the original.

using UnityEngine;
using UnityEditor;
using System.Reflection;
using System.Linq;

public class OnChangedCallAttribute : PropertyAttribute
{
    public string methodName;
    public OnChangedCallAttribute(string newMethodName)
    {
        methodName = newMethodName;
    }
}

[CustomPropertyDrawer(typeof(OnChangedCallAttribute))]
public class OnChangedCallAttributePropertyDrawer : PropertyDrawer
{
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        EditorGUI.BeginChangeCheck();
        EditorGUI.PropertyField(position, property, label);

        bool valueChanged = EditorGUI.EndChangeCheck();

        if(!valueChanged)
        {
            return;
        }

        OnChangedCallAttribute callAttribute = attribute as OnChangedCallAttribute;

        bool exist = GetParentPath(property.propertyPath, out string parentPath);

        if(!exist)
        {
            return;
        }

        SerializedProperty targetProperty = property.serializedObject.FindProperty(parentPath);

        object targetObject = targetProperty.boxedValue;// the problem is here. i only get a copy not a reference

        MethodInfo methodInfo = targetObject.GetType().GetMethod(callAttribute.methodName);
        
        if(methodInfo == null)  
        {
            Debug.LogWarning("Failed to get the method named : " + callAttribute.methodName + " at path " + parentPath);
            return;
        }

        if(!methodInfo.GetParameters().Any())
        {
            methodInfo.Invoke(targetObject, null);
        }

        targetProperty.serializedObject.ApplyModifiedProperties();
    }

    bool GetParentPath(string childPath, out string parentPath)
    {
        parentPath = "";

        if(!childPath.Contains('.'))
        {
            return false;
        }

        int lastDotIndex = childPath.LastIndexOf('.');
        parentPath = childPath[..lastDotIndex];
        return true;
    }
}

if anyone know a solution for this or an alternative way, that would be awesome!

If you believe you’re getting a copy, couldn’t you just assign that back to the boxedValue property?

1 Like

Oh wow. now I’m embarrassed to even call myself a developer. How didn’t i even think of that!
Thank you, kind stranger.

2 Likes