Reputation: 2069
For example of UnityEngine.UI.Text
It's contains text
variable for set the value of text as string.
Now, In my own class I use property(get;set) instead directly access the variable, This let me able to update views or fire some events when new value have set. The problem is when using property(get set) it'll not show this field in inspector and even in integration test tools.
But Unity's text component decided not to use get set. Which in my opinion I feel not comfortable for deal with value changed.
Question is how original UnityEngine.UI.Text
in text
variable can dealing with this?
I think It not just OnValidate()
because it can only work on editor. But text
variable also work on runtime scripting.
This function is called when the script is loaded or a value is changed in the inspector (Called in the editor only). https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnValidate.html
Upvotes: 4
Views: 20512
Reputation: 2069
Another solution I used:
public T car;
private T _car;
public Car { get => _car; set => _car = value; }
public void OnValidate() => Car = car;
Upvotes: 2
Reputation: 163
If you are not using a monobehavior (so you can do OnValidate()) or want to do polling than you could opt for going for an propertyattribute string to method reflection solution along the lines of this gist. Also below a simple implementation and example:
public class OnChangedCallAttribute : PropertyAttribute
{
public string methodName;
public OnChangedCallAttribute(string methodNameNoArguments)=> methodName = methodNameNoArguments;
}
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(OnChangedCallAttribute))]
public class OnChangedCallAttributePropertyDrawer : PropertyDrawer
{
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginChangeCheck();
EditorGUI.PropertyField(position, property);
if (EditorGUI.EndChangeCheck())
{
OnChangedCallAttribute at = attribute as OnChangedCallAttribute;
MethodInfo method = property.serializedObject.targetObject.GetType().GetMethods().Where(m => m.Name == at.methodName).First();
if (method != null && method.GetParameters().Count() == 0)// Only instantiate methods with 0 parameters
method.Invoke(property.serializedObject.targetObject, null);
}
}
}
#endif
Example:
using UnityEngine;
public class OnChangedCallTester : MonoBehaviour
{
public bool UpdateProp = true;
[SerializeField]
[OnChangedCall("ImChanged")]
private int myPropVar;
public int MyProperty
{
get => myPropVar;
set { myPropVar = value; ImChanged(); }
}
public void ImChanged() => Debug.Log("I have changed to" + myPropVar);
private void Update()
{
if (UpdateProp)
MyProperty++;
}
}
Upvotes: 5
Reputation: 4744
You just can't. That's why most components in Unity poll the value they are relying on every single frame.
If you really want to detect changes, you can do something like this:
public sometype Field;
private sometype _previousValueOfField;
public void Awake()
{
_previousValueOfField = Field;
}
public void Update()
{
if(Field != _previousValueOfField)
{
_previousValueOfField = Field;
// Execute some logic regarding the change of the field there
}
}
(By the way that's another reason why public fields are evil and I hate Unity for relying on them.)
Upvotes: 0
Reputation: 20028
There is no real way other than to check if the text has changed with respect to a cached "previous" value. In the absence of extension properties you'll simply have to do so manually.
Upvotes: 0