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!