Unity C#,脚本知道公共变量(非属性)何时发生变化

时间:2016-06-22 03:39:28

标签: c# unity3d getter-setter

例如UnityEngine.UI.Text

它包含text变量,用于将文本值设置为字符串。

现在,在我自己的类中,我使用property(get; set)而不是直接访问变量,这使我能够在设置新值时更新视图或触发某些事件。问题是当使用属性(get set)时,它不会在检查器中甚至在集成测试工具中显示此字段。

但是Unity的文本组件决定不使用get set。在我看来,我认为处理价值变得不舒服。

问题是UnityEngine.UI.Text变量中的原始text如何处理此问题?

我认为这不只是OnValidate(),因为它只能在编辑器上运行。但text变量也适用于运行时脚本。

  

加载脚本或值时调用此函数   在检查器中更改(仅在编辑器中调用)。   https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnValidate.html

4 个答案:

答案 0 :(得分:1)

我使用的另一种解决方案。

public T car;
private T _car;

public Car {
    get {
        return this._car;
    }
    set {
        this._car = value;
    }
}

public void OnValidate() {
     this.Car = car;
}

答案 1 :(得分:0)

除了检查文本是否相对于缓存的“之前”值更改之外,没有其他方法。如果没有扩展属性,您只需手动执行此操作即可。

答案 2 :(得分:0)

你不能。这就是为什么Unity中的大多数组件都会轮询它们依赖于每一帧的价值。

如果您确实想要检测更改,可以执行以下操作:

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        
    }
}

(顺便说一下,公共领域是邪恶的另一个原因,我讨厌Unity依赖它们。)

答案 3 :(得分:0)

如果您不使用单行为(因此可以执行OnValidate())或要进行轮询,则可以选择沿着this gist的行将属性归因字符串分配给方法反射解决方案。同样在下面的简单实现和示例中:

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

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

示例:

using UnityEngine;

public class OnChangedCallTester : MonoBehaviour
{
    public bool UpdateProp = true;

    [SerializeField]
    [OnChangedCall("ImChanged")]
    private int myPropVar;

    public int MyProperty
    {
        get { return myPropVar; }
        set { myPropVar = value; ImChanged();  }
    }


    public void ImChanged()
    {
        Debug.Log("I have changed to" + myPropVar);
    }

    private void Update()
    {
        if(UpdateProp)
            MyProperty++;
    }
}