【问题标题】:How to implement OnValueChange for any type class field in Unity如何为 Unity 中的任何类型类字段实现 OnValueChange
【发布时间】:2020-03-22 18:20:43
【问题描述】:

我正在尝试实现 OnValueChanged 方法,该方法将在更改目标字段时自动调用。例如,我有一个统一的 MonoBehaviour 类,如果它的枚举字段值发生更改,则执行一些代码。这是伪代码

public class SomeClass : MonoBehaviour {

   public enum SomeEnum { Value1, Value2 }

   public SomeEnum MyEnum;

   void Update() {
       if(MyEnum value isChanged){
           call OnMyEnumChanged();
       }    
   }

   public void OnMyEnumChanged() {

   }

}

希望我的问题很清楚,任何建议都非常感谢

【问题讨论】:

  • 在字段上放一个getter和setter,在设置时,调用一个deligate for onenumchanged
  • 我试过了,但它不起作用,因为当我从统一编辑器更改值时,没有检测到值变化
  • 如果您在编辑器中使用此脚本,请考虑使用ExecuteInEditMode 属性。 docs.unity3d.com/ScriptReference/ExecuteInEditMode.html
  • 不,不。这不是我想要的
  • @UnityDev define if it's enum field value is changed .. 你的意思是通过代码还是通过 Inspector?

标签: c# unity3d game-development


【解决方案1】:

在 google 上查找了一些信息后,我发现了 OnValidate 方法,当从编辑器/检查器更改某些内容时调用该方法。这是我编写的用于处理来自编辑器的值更改的代码

public class SomeClass : MonoBehaviour {

    public enum SomeEnum { Value1, Value2 }

    public SomeEnum SomeEnumProperty {
        get => myEnum;
        set {
            if (myEnumObserver == value)
                return;
            myEnum = value;
            myEnumObserver = myEnum;
            OnMyEnumChanged();
        } 
    }

    [SerializeField]
    private SomeEnum myEnum;
    private SomeEnum myEnumObserver;

    void OnValidate() {
        if (SomeEnumProperty != myEnumObserver) {
            SomeEnumProperty = myEnum;
        }
    }

    void Update() {

    }

    public void OnMyEnumChanged() {
       Debug.Log("ValueChanged Called");
    }

}

【讨论】:

  • 我认为你需要交换这些行的顺序:myEnum = value;myEnumObserver = myEnum;
  • 您还应该完全删除现在为空的Update 方法!无论如何,只要它存在,Unity就会调用它,这只会浪费资源。此外,OnValidate 仅在 UnityEditor 中调用 .. 而不是在构建的游戏中调用
【解决方案2】:

通常我们会实现INotifyPropertyChanged,但我不知道这在 Mono/Unity 中能走多远。

物有所值:

using System.ComponentModel;

public class SomeClass : MonoBehaviour, INotifyPropertyChanged {

   public enum SomeEnum { Value1, Value2 }

   SomeEnum myEnum
   public SomeEnum MyEnum
   {
       get { return myEnum; }
       set
       {
           if (myEnum == value)
               return;

           myEnum = value;
           OnPropertyChanged("MyEnum");
       }
   }

   void Update() {

   }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

}

【讨论】:

  • 您还应该完全删除现在为空的Update 方法!只要它存在,Unity 就会调用它,这只会浪费资源
  • @UnityDev 你的具体情况是什么?
  • 我的情况是,当我的自定义枚举值发生变化时,我想调用一些方法,我做到了,感谢您的帮助
  • @derHugo 我怀疑 Unity 会调用私有方法。这只是为了说明目的,我从Update() 中删除了代码,这就是我离开它的原因。
  • @rfmodulator 以及您认为private void Startprivate void Update 等中的任何一个是如何被调用的?如果它们存在,Unity 会将它们作为消息调用;)它们是否为private 并不重要。在这种情况下,至少将其注释掉;)
猜你喜欢
  • 1970-01-01
  • 2017-06-15
  • 2016-11-08
  • 1970-01-01
  • 2018-08-12
  • 1970-01-01
  • 1970-01-01
  • 2018-03-13
相关资源
最近更新 更多