값 변경시 Method 호출 (Attribute - Change Call)
값이 변경될때 해당 Method를 호출하는 기능이다.
< 사용방법 >
[System.Serializable]
public class ScreenChangeAction
{
[Utill.OnChangedCall("RatioCalc")]
[SerializeField]
private int width;
public void RatioCalc()
{
// This method will be called whenever 'width' changes in the inspector
Debug.Log("RatioCalc method called. Width changed to: " + width);
}
}
반응형
< Attribute >
using UnityEngine;
using UnityEditor;
using System.Linq;
using System.Reflection;
namespace Utill
{
// Custom attribute to mark a field with a method to call when it changes
public class OnChangedCallAttribute : PropertyAttribute
{
public string methodName;
public OnChangedCallAttribute(string methodNameNoArguments)
{
methodName = methodNameNoArguments;
}
}
// Custom property drawer to handle the attribute
[CustomPropertyDrawer(typeof(OnChangedCallAttribute))]
public class OnChangedCallAttributePropertyDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
// Start listening for changes to the property
EditorGUI.BeginChangeCheck();
EditorGUI.PropertyField(position, property, label);
// If no change, exit early
if (!EditorGUI.EndChangeCheck()) return;
// Apply modified properties to ensure changes are committed
property.serializedObject.ApplyModifiedProperties();
// Get the target object and the method name from the attribute
var targetObject = property.serializedObject.targetObject;
var callAttribute = (OnChangedCallAttribute)attribute;
var methodName = callAttribute.methodName;
// Resolve the parent object if the field is part of a nested structure or list
object parentObject = GetParentObjectOfProperty(property, targetObject);
// Get the method info and invoke it if found
var methodInfo = parentObject.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (methodInfo != null && methodInfo.GetParameters().Length == 0)
{
methodInfo.Invoke(parentObject, null);
}
else
{
Debug.LogError($"OnChangedCall error: No method named '{methodName}' taking no arguments found in {parentObject.GetType().Name}");
}
}
// Helper method to resolve the parent object of a serialized property
private object GetParentObjectOfProperty(SerializedProperty prop, object targetObject)
{
var path = prop.propertyPath.Replace(".Array.data[", "[");
var elements = path.Split('.');
foreach (var element in elements.Take(elements.Length - 1))
{
if (element.Contains("["))
{
var elementName = element.Substring(0, element.IndexOf("["));
var index = int.Parse(element.Substring(element.IndexOf("[")).Replace("[", "").Replace("]", ""));
targetObject = GetValue(targetObject, elementName, index);
}
else
{
targetObject = GetValue(targetObject, element);
}
}
return targetObject;
}
private object GetValue(object source, string name)
{
if (source == null)
return null;
var type = source.GetType();
var field = type.GetField(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
if (field == null)
{
var property = type.GetProperty(name, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
return property?.GetValue(source, null);
}
return field.GetValue(source);
}
private object GetValue(object source, string name, int index)
{
var enumerable = GetValue(source, name) as System.Collections.IEnumerable;
var enumerator = enumerable?.GetEnumerator();
for (int i = 0; i <= index; i++)
{
if (!enumerator.MoveNext()) return null;
}
return enumerator.Current;
}
}
}
사진
★☆☆
반응형
'개발 > Unity' 카테고리의 다른 글
Unity) 원형 룰렛(Roulette) 만들기 (2) | 2024.09.10 |
---|---|
Unity) 선택된 Uniy Editor 찾기 (EditorWindowDector) (2) | 2024.09.07 |
문제해결)Unity is running as administrator (0) | 2024.09.03 |
Unity) 숫자 롤링 애니메이션 (Number Rolling), 숫자 플립 애니메이션( Number Flip) (1) | 2024.08.28 |
Unity) 프레임 캡처 기반 그래픽 디버거 : (렌더독 RenderDoc) (0) | 2024.08.28 |
댓글