如何从统一自定义编辑器中的可编写脚本对象数组中获取值?

Posted

技术标签:

【中文标题】如何从统一自定义编辑器中的可编写脚本对象数组中获取值?【英文标题】:How to get a value from an array of scriptable objects in unity custom editor? 【发布时间】:2021-12-26 01:05:06 【问题描述】:

我正在尝试制作自定义编辑器,但无法从数组中的可编写脚本的对象中获取值。 这是包含 CharacterData 可脚本化对象的 FightData 脚本。

public class FightData : ScriptableObject 
    public CharacterData [] enemyDatas;

CharacterData 包含统计数据。

public class CharacterData : ScriptableObject 

    public CharacterStats stats;

这里是 CharacterStats

[System.Serializable]
public class CharacterStats

    public float HP;
    public float damage;
    public float defense;
    public float attackInterval;

    public CharacterStats()
        HP = 0f;
        damage = 0f;
        defense = 0f;
        attackInterval = 2f;
    

我想总结所有统计数据并将它们显示在 FightData 的自定义编辑器中。但统计数据始终为空。 这是我的方法:

[CustomEditor(typeof(FightData))]
public class FightDataEditor : Editor

    SerializedProperty _enemyDatas;


    private void OnEnable()   
        _enemyDatas = serializedObject.FindProperty("enemyDatas");     
    

    public override void OnInspectorGUI()
        serializedObject.Update();
        EditorGUILayout.PropertyField(_enemyDatas);

        var result = 0f;
        int length = _enemyDatas.arraySize;
        for (int i = 0; i < length; i++)
        
            SerializedProperty stats = _enemyDatas.GetArrayElementAtIndex(i).serializedObject.FindProperty("stats");
            if(stats == null)
                Debug.Log(stats);
                continue;
            
            result += stats.FindPropertyRelative("HP").floatValue;
            result += stats.FindPropertyRelative("damage").floatValue;
            result += stats.FindPropertyRelative("defense").floatValue;
        

        EditorGUILayout.Space(); 
        EditorGUILayout.LabelField("Total Power", EditorStyles.boldLabel);
        EditorGUILayout.FloatField(result);

 
        serializedObject.ApplyModifiedProperties();
    

【问题讨论】:

【参考方案1】:

FindPropertyRelative 仅在它实际上是一个嵌套的“普通”序列化类并序列化为 YAML 值时才有效。

但是对于ScriptableObject(通常是从UnityEngine.Object 继承的任何东西),您存储的不是序列化的,而只是UnityEngine.Object 引用

您需要获取相应的SerializedObject 实例,例如

[CustomEditor(typeof(FightData))]
public class FightDataEditor : Editor

    SerializedProperty _enemyDatas;


    private void OnEnable() 
      
        _enemyDatas = serializedObject.FindProperty("enemyDatas");     
    

    public override void OnInspectorGUI()
   
        serializedObject.Update();
        EditorGUILayout.PropertyField(_enemyDatas);

        var result = 0f;
        int length = _enemyDatas.arraySize;
        for (int i = 0; i < length; i++)
        
            // Get the element SerializedProperty
            var element = _enemyDatas.GetArrayElementAtIndex(i);

            // The field exists but no object is referenced
            if(!element.objectReferenceValue)
            
                continue;
            

            // otherwise get a serialized object for this reference
            var sObj = new SerializedObject(element.objectReferenceValue);

            // stats is now a property of that serialized object
            var stats = sObj.FindProperty("stats");

            // The other values are now further nested properties of the serialized CharacterStats class
            result += stats.FindPropertyRelative("HP").floatValue;
            result += stats.FindPropertyRelative("damage").floatValue;
            result += stats.FindPropertyRelative("defense").floatValue;
        

        EditorGUILayout.Space(); 
        EditorGUILayout.LabelField("Total Power", EditorStyles.boldLabel);
        EditorGUILayout.FloatField(result);

 
        serializedObject.ApplyModifiedProperties();
    

注意:如果您要公开这些 SerializedObjects 的字段并且还想更改它们,您还需要相应地调用

sObj.Update();

...

sObj.ApplyModifiedProperties();

在智能手机上输入,但我希望思路清晰

【讨论】:

以上是关于如何从统一自定义编辑器中的可编写脚本对象数组中获取值?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我在 Android 上运行之间会丢失可编写脚本对象中的数据,但在编辑器中却没有?

如何从自定义模型对象数组中获取特定键的值

Silverlight 数据绑定无法从可编写脚本的成员中工作

可编写脚本的插件,Javascript 返回未定义

在可编写脚本的对象UNITY 5中存储方法

如何使 Qt 中的类既可编写脚本又可序列化?