首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何根据统一检查器中没有MonoBehaviour的另一个变量的值隐藏变量

如何根据统一检查器中没有MonoBehaviour的另一个变量的值隐藏变量
EN

Stack Overflow用户
提问于 2022-10-12 06:26:14
回答 1查看 46关注 0票数 -1

我有一个类,我想根据bool "segmentEnd“的值隐藏浮点数"isAStillFrame”。

我不能使用MonoBehaviour的原因是我需要类" VideoSegment“在VideoSegment所在的脚本中的序列化列表中。这个是可能的吗?现在,更改isAStillFrame的值不起任何作用。

类以修改

code

代码语言:javascript
运行
复制
public class VideoSegment
{
    public string segmentName;
    public bool isAStillFrame;
    public float segmentStart;
    public float segmentEnd;
    public List<VideoSegmentCue> segmentCues;
    public VideoSegmentAction endAction;
}

code

编辑器文件夹中的编辑器脚本

code

代码语言:javascript
运行
复制
using UnityEditor;
using UnityEngine;
using System.Collections.Generic;
using System.Reflection;

    [CustomEditor(typeof(VideoSegment)), CanEditMultipleObjects]
    public class SegmentedVideoPlayerEditor : Editor
    {
        private List<boolStruct> structList;

        public void OnEnable()
        {
            structList = new List<boolStruct>();
            SetBools();
        }

        private void SetBools()
        {
            HideIf("isAStillFrame", true, "segmentEnd");
        }

        private void HideIf(string boolName, bool boolValue, string fieldName)
        {
            boolStruct _boolStruct = new boolStruct()
            {
                targetBoolName = boolName,
                targetBoolValue = boolValue,
                targetVarName = fieldName,
            };
            structList.Add(_boolStruct);
        }
        public override void OnInspectorGUI()
        {
            serializedObject.Update();
            var obj = serializedObject.GetIterator();
            if (obj.NextVisible(true))
            {
                do
                {
                    bool visible = true;
                    foreach (var i in structList)
                    {
                        if (i.targetVarName == obj.name)
                        {
                            FieldInfo boolName = target.GetType().GetField(i.targetBoolName);
                            var boolValue = boolName.GetValue(target);
                            if (boolValue.ToString() != i.targetBoolValue.ToString())
                                visible = false;
                            else
                            {
                                visible = true;
                                break;
                            }
                        }
                    }
                    if (visible)
                        EditorGUILayout.PropertyField(obj, true);
                }
                while (obj.NextVisible(false));
            }
            serializedObject.ApplyModifiedProperties();
        }
        private struct boolStruct
        {
            public string targetBoolName { get; set; }
            public bool targetBoolValue { get; set; }
            public string targetVarName { get; set; }
        }
    }

code

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-10-12 07:49:42

如果您没有从MonoBehaviourScriptableObject继承(或者一般是从UnityEngine.Object继承),那么使用自定义Editor是错误的。

Editor用于为某个可选择的资产类型实现一个完整的检查器。

您更愿意使用的是一个定制的PropertyDrawer,它看起来可能类似于。

代码语言:javascript
运行
复制
// First of all your class needs to be serializable
// otherwise it won't show up in the Inspector at all
[Serializable]
public class VideoSegment
{
    public string segmentName;
    public bool isAStillFrame;
    public float segmentStart;
    public float segmentEnd;
    public List<VideoSegmentCue> segmentCues;
    public VideoSegmentAction endAction;
}

然后

代码语言:javascript
运行
复制
[CustomPropertyDrawer(typeof(VideoSegment))]
public class VideoSegmentDrawer : PropertyDrawer
{
    // First you have to define how much vertical space your custom drawer should reserve 
    public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
    {
        // I simply assume you want to fold your type so in this case
        // it would be only the foldout label
        if (!property.isExpanded)
        {
            return EditorGUIUtility.singleLineHeight;
        }

        // link up the properties
        var segmentName = property.FindPropertyRelative("segmentName");
        var isAStillFrame = property.FindPropertyRelative("isAStillFrame");
        var segmentStart = property.FindPropertyRelative("segmentStart");
        var segmentEnd = property.FindPropertyRelative("segmentEnd");
        var segmentCues = property.FindPropertyRelative("segmentCues");
        var endAction = property.FindPropertyRelative("endAction");

        // assuming we later on use the default drawers for all properties
        // we an also just use the default heights for them
        return EditorGUIUtility.singleLineHeight
            + EditorGUI.GetPropertyHeight(segmentName)
            + EditorGUI.GetPropertyHeight(isAStillFrame)
            + EditorGUI.GetPropertyHeight(segmentStart)
            // if your bool is checked we want to skip this field later
            // so we also don't need the space for it
            + (isAStillFrame.boolValue ? 0 : EditorGUI.GetPropertyHeight(segmentEnd))
            + EditorGUI.GetPropertyHeight(segmentCues)
            + EditorGUI.GetPropertyHeight(endAction);
    }

    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
    {
        // Using BeginProperty / EndProperty on the parent property means that
        // prefab override logic works on the entire property.
        EditorGUI.BeginProperty(position, label, property);

        // calculate rect for the foldout label
        var labelRect = position;
        labelRect.height = EditorGUIUtility.singleLineHeight;
        position.y += EditorGUIUtility.singleLineHeight;

        // Draw foldout label
        property.isExpanded = EditorGUI.Foldout(labelRect, property.isExpanded, label);
        
        // if expanded draw the rest
        if (property.isExpanded)
        {
            // again link up poperties
            var segmentName = property.FindPropertyRelative("segmentName");
            var isAStillFrame = property.FindPropertyRelative("isAStillFrame");
            var segmentStart = property.FindPropertyRelative("segmentStart");
            var segmentEnd = property.FindPropertyRelative("segmentEnd");
            var segmentCues = property.FindPropertyRelative("segmentCues");
            var endAction = property.FindPropertyRelative("endAction");
 
            // indentation - I was lazy to look it up so just used an arbitrary value
            position.x += 5;
            position.width -= 5;

            // Calculate rect and draw segmentName
            var segmentNameRect = position;
            segmentNameRect.height = EditorGUI.GetPropertyHeight(segmentName);
            position.y += segmentNameRect.height;
            EditorGUI.PropertyField(segmentNameRect, segmentName);

            // Calculate rect and draw isAStillFrame
            var isAStillFrameRect = position;
            isAStillFrameRect.height = EditorGUI.GetPropertyHeight(isAStillFrame);
            position.y += isAStillFrameRect.height;
            EditorGUI.PropertyField(isAStillFrameRect, isAStillFrame);

            // Calculate rect and draw segmentStart
            var segmentStartRect = position;
            segmentStartRect.height = EditorGUI.GetPropertyHeight(segmentStart);
            position.y += segmentStartRect.height;
            EditorGUI.PropertyField(segmentStartRect, segmentStart);

            // skip if your bool is set
            if (!isAStillFrame.boolValue)
            {
                // Calculate rect and draw segmentEnd
                var segmentEndRect = position;
                segmentEndRect.height = EditorGUI.GetPropertyHeight(segmentEnd);
                position.y += segmentEndRect.height;
                EditorGUI.PropertyField(segmentEndRect, segmentEnd);
            }

            // Calculate rect and draw segmentCues
            var segmentCuesRect = position;
            segmentCuesRect.height = EditorGUI.GetPropertyHeight(segmentCues);
            position.y += segmentCuesRect.height;
            EditorGUI.PropertyField(segmentCuesRect, segmentCues);

            // Calculate rect and draw endAction
            var endActionRect = position;
            endActionRect.height = EditorGUI.GetPropertyHeight(endAction);
            position.y += endActionRect.height;
            EditorGUI.PropertyField(endActionRect, endAction);
        }

        EditorGUI.EndProperty();
    }
}

这看起来就像

注意:我没有您的VideoSegmentCueVideoSegmentAction类型,所以我只是在演示中使用Vector3 ;)

代码语言:javascript
运行
复制
public class Test : MonoBehaviour
{
    public VideoSegment singleSegment;

    public List<VideoSegment> listOfSegments;
}

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

https://stackoverflow.com/questions/74037328

复制
相关文章

相似问题

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