首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从另一个脚本表中序列化Scriptable中的字段

从另一个脚本表中序列化Scriptable中的字段
EN

Stack Overflow用户
提问于 2021-10-18 13:27:17
回答 1查看 32关注 0票数 0

我在UnityEditor中发现了一个关于可脚本化对象的有趣“问题”。下面是一个简单的例子:

我有一个可脚本化的类ScriptableExpressionBulder,它包含一些列表和一个浮点型字段。然后我有另一个类ScriptableExpressionCreator,它保存了前面提到的可脚本化对象的列表。代码如下所示:

代码语言:javascript
复制
public class ScriptableExpressionBuilder : ScriptableObject
        {
           public List<MultipleExpressionBuilder> multipleExpressionBuilder;
           public float delay;
        }



public class ScriptableExpressionCreator : ScriptableObject {

        public List<ScriptableExpressionBuilder> List;

}

在创建延迟时,(MultipleExpressionBuilder)中的字段出现得很好,但它还在末尾添加了第二个字段“ScriptableExpressionBuilder”(这在这一点上是完美的)。

现在是有趣的部分:

第二个类ScriptableExpressionCreator保存以前的脚本列表,但它不序列化当前脚本中的"delay“字段。唯一序列化的字段是一个可编写脚本的类。

有没有办法将ScriptableExpressionBuilder中的字段序列化到另一个包含这些脚本的列表的脚本表中,这样我基本上就可以设置调用这些表达式的延迟。然而,我可以在原始脚本的检查器中填充字段,但由于每个延迟是不同的,因此不能重复使用。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-10-19 07:21:03

您删除了问题,但我投票重新打开它,因为我已经开始编写解决方案,并在您删除它时完成,我认为这现在做了您想要的事情,并为您在需要的地方进一步扩展它提供了一个很好的起点;)

然而,这不是一个真正的问题,不可能是内置的。

对于ScriptableObject (以及从UnityEngine.Object继承的任何其他内容),检查器默认绘制一个对象字段。如果你想画其他东西,你需要一个custom editor script。为了在另一个检查器的检查器中公开其他UnityEngine.Object引用的字段,实际上并不需要自定义检查器。

它可能看起来有点像(例如,现在假设您只想另外公开delay字段)

代码语言:javascript
复制
#if UNITY_EDITOR
using System;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;

[CustomEditor(typeof(ScriptableExpressionCreator))]
public class ScriptableExpressionCreatorEditor : Editor
{
    private SerializedProperty _list;

    // I know ... but that's your fault for naming th field List :P
    private ReorderableList _listList;

    // For Edito this is called when the object gains focus and the Inspector is loaded for this scriptableobject instance
    private void OnEnable()
    {
        // Find and link the serialized field called "List"
        _list = serializedObject.FindProperty(nameof(ScriptableExpressionCreator.List));

        // Initialize and configure the ReorderableList to draw the referenced elements in the way we want
        _listList = new ReorderableList(serializedObject, _list, true, true, true, true)
        {
            // How is te list header drawn?
            drawHeaderCallback = rect => EditorGUI.LabelField(rect, _list.displayName),

            // how should each element be drawn?
            drawElementCallback = (rect, index, active, focused) =>
            {
                // get the current element
                var element = _list.GetArrayElementAtIndex(index);

                // draw the default object reference field with the height of a single line without the label
                EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), element,  GUIContent.none);

                // if no object is referenced do nothing more
                if (!element.objectReferenceValue) return;

                // move one line lower
                rect.y += EditorGUIUtility.singleLineHeight;

                // get a serializedObject of the reference
                var elementsSerializedObject = new SerializedObject(element.objectReferenceValue);

                // same as in our own OnInspectorGUI method below loads the current values
                elementsSerializedObject.Update();

                // for now assuming you only want the delay field
                var delay = elementsSerializedObject.FindProperty(nameof(ScriptableExpressionBuilder.delay));

                // draw the delay field
                EditorGUI.PropertyField(new Rect(rect.x, rect.y, rect.width, EditorGUIUtility.singleLineHeight), delay);

                // same as in our own OnInspectorGUI method below writes back changed values and handles undo/redo marking dirty etc
                elementsSerializedObject.ApplyModifiedProperties();
            },

            // how do we get the height of one element?
            elementHeightCallback = index =>
            {
                // get the current element
                var element = _list.GetArrayElementAtIndex(index);

                // if nothing is referenced we only need a single line
                if (!element.objectReferenceValue)
                {
                    return EditorGUIUtility.singleLineHeight;
                }

                // otherwise we need two lines, one for the object field and one for the delay field
                return EditorGUIUtility.singleLineHeight * 2;
            }
        };
    }

    public override void OnInspectorGUI()
    {
        // draw the script field
        DrawScriptField();

        // loads current values into the serialized version
        serializedObject.Update();

        // draw the list according to the settings above
        _listList.DoLayoutList();

        // writes bac any changed values into the actual instance and handles undo/redo marking dirty etc
        serializedObject.ApplyModifiedProperties();
    }

    // Draws the default script field on the top the Inspector
    private void DrawScriptField()
    {
        // The script field is disabled since nobody is supposed to evr change it
        EditorGUI.BeginDisabledGroup(true);
        EditorGUILayout.ObjectField("Script", MonoScript.FromScriptableObject((ScriptableExpressionCreator)target), typeof(ScriptableExpressionCreator), false);
        EditorGUI.EndDisabledGroup();

        // leave a little space between the script field and the actual inspector conten
        EditorGUILayout.Space();
    }
}
#endif

现在,它看起来像这样

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69616963

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档