Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# OnValueChanged在可脚本对象统一中_C#_Unity3d - Fatal编程技术网

C# OnValueChanged在可脚本对象统一中

C# OnValueChanged在可脚本对象统一中,c#,unity3d,C#,Unity3d,我是否可以在C#Unity中的类扩展ScriptableObject中的变量/属性上使用某些类型的OnValueChanged()或OnValueChanged属性,以便在inspector中更改其资产文件中该变量/属性的值时调用另一个方法?还是有其他方法可以达到这个目的?您可以用它来存档。下面是一个可以监视字段和属性更改的最小示例 公共类CustomType:ScriptableObject{ 公共领域; 私有财产; 公共财产{ 获取{return myProperty;} 设置{ 如果(值!

我是否可以在C#Unity中的类扩展ScriptableObject中的变量/属性上使用某些类型的OnValueChanged()或OnValueChanged属性,以便在inspector中更改其资产文件中该变量/属性的值时调用另一个方法?还是有其他方法可以达到这个目的?

您可以用它来存档。下面是一个可以监视字段和属性更改的最小示例

公共类CustomType:ScriptableObject{ 公共领域; 私有财产; 公共财产{ 获取{return myProperty;} 设置{ 如果(值!=myProperty){ //在这里做事 myProperty=值; } } } OnMyFieldChanged上的公共无效(int-from,int-to){ //在这里做事 } } #如果统一编辑器 [CustomEditor(typeof(CustomType))] 类CustomTypeEditor:Editor{ 公共覆盖无效OnInspectorGUI(){ CustomType CustomType=(CustomType)目标; int field=EditorGUILayout.IntField(“field”,customType.myField); 如果(字段!=customType.myField){ customType.OnMyFieldChanged(customType.myField,字段); customType.myField=字段; } customType.MyProperty=EditorGUILayout.IntField(“属性”,customType.MyProperty); } } #恩迪夫 只有在inspector中打开此对象时,此操作才有效。如果要将此对象作为另一个对象的一部分,则必须改用。这些编辑器与自定义编辑器非常相似。
这是一个非常基本的示例,可以说明使用自定义编辑器可以解决问题,但如果打算使用它们,您可能希望进一步了解该主题。

如果您的类不是从monobehavior for OnValidate()继承的,则可以在中找到一个简单的propertydrawer解决方案或者希望避免为每个类创建自定义编辑器。下面是一个简单的实现和示例:

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++;
    }
}
自由资产具有一个属性,您可以使用该属性在值通过检查器更改时触发该属性。下面是一个在Inspector中显示下拉列表的示例:

[Dropdown("LevelNames")]
[OnValueChanged("OnLevelChanged")]
public string currentLevelName;

private List<string> LevelNames {
    get {
        return new List<string>() { "Level 1", "Level 2", "Level 3" };
    }
}

private void OnLevelChanged() {
    Debug.LogFormat("OnLevelChanged: {0}", currentLevelName);
}
[下拉列表(“LevelNames”)]
[OnValueChanged(“OnLevel更改”)]
公共字符串currentLevelName;
私有列表级别名称{
得到{
返回新列表(){“级别1”、“级别2”、“级别3”};
}
}
私有void OnLevelChanged(){
LogFormat(“OnLevelChanged:{0}”,currentLevelName);
}

您可以执行
OnValidate
功能来检测inspector中的值何时更改。但是,现在更改值的唯一方法是使用私有“备份字段”并将该值与序列化字段进行比较。您要监视的值是否为自定义类型?如果是,您可以向其添加事件处理程序。是的,它是自定义类型,并且是类扩展ScriptableObject中的变量。我创建了该类的一个资产文件,我希望在通过inspector更改该变量(在资产文件中)的值时调用一个方法。这个方法应该是在那个类中的好主意-谢谢-但是这段代码在编写时似乎不适用于复合检查器字段,比如System.Serializable structs。此时会出现小的“展开”箭头,每次单击回调时都会调用它(并按预期进行切换),但较低级别结构的字段不再显示在检查器中。关于如何扩展它以使其在这种情况下工作,您有什么想法吗?