【问题标题】:Customizing inspector by Enum type likes通过枚举类型自定义检查器喜欢
【发布时间】:2017-06-15 02:52:34
【问题描述】:

有一个包含多种运动类型的平台类。 TypeA 在航路点之间启动时是 AutoMove 当特定布尔值为真时,TypeB 随重力下降。 我通过选择自己的 Enum 类型来控制这些不同的行为。

我现在要做的是只能在检查器上看到与运动类型匹配的那些变量,因为 TypeA 使用 TypeB 完全忽略的航路点系统,并且检查器上剩余的所有未使用的变量只会让事情变得混乱和混乱。

我可以一次让他们成为自己的班级,但如果我坚持并尝试这样做:这可以做到吗?我该怎么做?

要问的另一件事是,是否有像我这样的类在性能效率方面更好?在自己的脚本上上课?或者只是不打扰性能?如果没有显着的性能差异,我打算像以前一样这样做。

编辑:添加了带有指示的已发布检查员。 红色是选择跟随哪个运动功能的枚举 1.是一种遵循航点系统并漫游的运动类型 2.是与PC接触时跌倒的运动类型之一 3. 是一种只有在电动布尔值为真时才会移动的运动类型

【问题讨论】:

  • 如果你能提供一些直观的解释会更有帮助,因为不是每个人都对你遇到的问题有深刻的理解。
  • 构建您自己的自定义检查器:unity3d.com/learn/tutorials/topics/interface-essentials/…。您可以在需要时通过选择当前枚举和内容来显示某些字段。互联网上有很多文档。
  • @Tengku 谢谢。刚刚添加了示例图片!
  • @AlexFerretti 感谢您的链接。我已经尝试实现它们,添加的图像就是结果。但仍然没有设法到达我想要的地方。找不到我正在寻找的命令隐藏/显示枚举,虽然:P
  • 也许这个answers.unity3d.com/questions/417837/… 是您要找的?基本上,您只需要获取枚举的值并对其进行切换,在每种情况下,您都会显示所需的字段

标签: c# unity3d enums


【解决方案1】:

您需要实现自己的自定义检查器。这个话题有Unity's official tutorial。自定义检查器使用 GUI 类,当且仅当满足条件时,您需要检查您的条件并绘制一个字段。

这是我从Change Inspector Variables Depending On Enum 获取的示例代码。通过此代码,您将了解如何从目标类动态获取 enum 字段的值。

~/Assets/PropertyHolder.cs

using System.Collections;
using UnityEngine;


public class PropertyHolder : MonoBehaviour
{
    public enum Status { A, B, C };

    public Status state;

    public int valForAB;

    public int valForA;
    public int valForC;

    public bool controllable;

    void Start()
    {

    }

    void Update()
    {

    }
}

~/Assets/Editor/PropertyHolderEditor.cs

using UnityEditor;
using UnityEngine;

[CustomEditor(typeof (PropertyHolder)), CanEditMultipleObjects]
public class PropertyHolderEditor : Editor
{

    public SerializedProperty
    state_Prop,
    valForAB_Prop,
    valForA_Prop,
    valForC_Prop,
    controllable_Prop;

    void OnEnable()
    {
        // Setup the SerializedProperties
        state_Prop = serializedObject.FindProperty("state");
        valForAB_Prop = serializedObject.FindProperty("valForAB");
        valForA_Prop = serializedObject.FindProperty("valForA");
        valForC_Prop = serializedObject.FindProperty("valForC");
        controllable_Prop = serializedObject.FindProperty("controllable");
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();

        EditorGUILayout.PropertyField(state_Prop);

        PropertyHolder.Status st = (PropertyHolder.Status) state_Prop.enumValueIndex;

        switch (st)
        {
            case PropertyHolder.Status.A:
                EditorGUILayout.PropertyField(controllable_Prop, new GUIContent("controllable"));
                EditorGUILayout.IntSlider(valForA_Prop, 0, 10, new GUIContent("valForA"));
                EditorGUILayout.IntSlider(valForAB_Prop, 0, 100, new GUIContent("valForAB"));
                break;

            case PropertyHolder.Status.B:
                EditorGUILayout.PropertyField(controllable_Prop, new GUIContent("controllable"));
                EditorGUILayout.IntSlider(valForAB_Prop, 0, 100, new GUIContent("valForAB"));
                break;

            case PropertyHolder.Status.C:
                EditorGUILayout.PropertyField(controllable_Prop, new GUIContent("controllable"));
                EditorGUILayout.IntSlider(valForC_Prop, 0, 100, new GUIContent("valForC"));
                break;

        }

        serializedObject.ApplyModifiedProperties();
    }
}

这是仅在满足条件时才检查布尔和绘制的方法,来自Hide/Show properties dynamically in inspector。修改布尔检查部分以比较您使用上述代码找到的enum 值。

public class MyScript : MonoBehaviour
{
    public bool flag;
    public int i = 1;
}

[CustomEditor(typeof (MyScript))]
public class MyScriptEditor : Editor
{
    void OnInspectorGUI()
    {
        var myScript = target as MyScript;

        myScript.flag = GUILayout.Toggle(myScript.flag, "Flag");

        if (myScript.flag)
            myScript.i = EditorGUILayout.IntSlider("I field:", myScript.i, 1, 100);

    }
}

结合这两者你应该得到你想要的行为。

【讨论】:

  • 谢谢!我已经成功实施,我想我可以在这里进一步推进!非常感谢您的帮助!
  • 虽然这完美地回答了OP的问题,但我觉得它与统一的最佳实践不一致。看我下面的回复
【解决方案2】:

我认为制作 3 个独立的控制器脚本会更好,这些脚本都继承了一个 MovementType 接口(如果你想让它们保持链接在一起)。然后,您只需附加所需的控制器。所以如果是自动移动,你只需附加自动移动脚本。

界面将确保所有 3 种类型都保持某些操作方式并确保它们保持某些功能。我认为它们以某种方式相关,这就是为什么它们当前在同一个文件中。如果不只是创建没有界面的 3 个单独的脚本。

该界面可以让您强制某些对象定义运动类型。

您当前设置方式的问题是您有 1 个脚本做 4 件事。这违反了一些编程的最佳实践,尤其是 Unity 中每个脚本都应该可重用并且只执行一项主要任务的理念。

为阐述而编辑:

这个想法是划分行为。因此,如果您需要自动移动某些东西,您可以创建一个单独的脚本。然后在未来,如果你想让其他东西自动移动,比如说一个不同类型的游戏对象,类似于云之类的平台(想想马里奥),那么你也可以将你的自动移动脚本拖到那个游戏对象上。同样,在接触时坠落,您可能希望平台坠落,但有时您也可能希望砖块这样做。因此,对于您想要接触的积木,您只需为它们重用该脚本即可。

ScriptableObjects 可能不适用于这个问题。它们适用于游戏中有抽象事物的情况,例如库存。对于游戏中的实际对象,您希望使用附加脚本的标准游戏对象。

【讨论】:

  • 有一个最终目标,随之而来的是一个问题。首要任务(不是完成版本,而是功能方面)是我的设计师不必浏览脚本文件夹(尽管资产的良好组织可以解决这个问题)因为这个特定的脚本是关于整个游戏中的任何平台行为如果我也考虑过让它们成为 ScriptableObject,但我仍在学习它。然而,我的灰色区域是有效的,这在性能方面是有效的。由于我不是计算机工程师专业的(我实际上既是设计师又是艺术家,但首先是艺术家)
  • 我还没有走到这一步。在这个脚本中,一个平台目前有 4 种不同类型的移动行为,现在在你们的帮助下,我已经实现了我的第一个目标:在一个脚本中的所有平台行为,每个行为的变量都通过移动暴露在检查器上类型。现在是我试图了解性能方面的时候了。 ScriptableObject 对我来说是最引人注目的东西,但我在连接不同的移动类型时遇到了困难,这些移动类型在与 ScriptableObject 相同的插槽中也有不同的移动方法。
  • 看我上面的阐述
  • 感谢您的详细说明!我觉得我对 C# 编码和 Unity 的理解中的一些灰色区域正在填补:编码和将函数分割到自己的类和文件的一般概念。这是关于我觉得我可能需要一些代码审查的地方,而你的提示给了我一些关于去哪里的见解。我将开始将平台移动类型的功能分离为单独的脚本,并使用我现在在其他地方学到的自定义编辑器!
猜你喜欢
  • 1970-01-01
  • 2011-09-11
  • 2020-12-16
  • 1970-01-01
  • 2013-03-20
  • 2021-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多