2024-07-14 Unity插件 Odin Inspector2 —— Essential Attributes

news2024/9/21 19:07:58

文章目录

  • 1 说明
  • 2 重要特性
    • 2.1 AssetsOnly / SceneObjectsOnly
    • 2.2 CustomValueDrawer
    • 2.3 OnValueChanged
    • 2.4 DetailedInfoBox
    • 2.5 EnableGUI
    • 2.6 GUIColor
    • 2.7 HideLabel
    • 2.8 PropertyOrder
    • 2.9 PropertySpace
    • 2.10 ReadOnly
    • 2.11 Required
    • 2.12 RequiredIn(*)
    • 2.13 Searchable
    • 2.14 ShowInInspector
    • 2.15 Title
    • 2.16 TypeFilter
    • 2.17 TypeInfoBox
    • 2.18 ValidateInput
    • 2.19 ValueDropdown

1 说明

​ 本章介绍 Odin Inspector 插件中重要特性的使用方法。

2 重要特性

2.1 AssetsOnly / SceneObjectsOnly

使目标对象在 Inspector 窗口中只能关联资源 / 场景对象,限制拖拽的资源类型。

image-20240715004717713
// SceneAndAssetsOnlyExamplesComponent.cs

using Sirenix.OdinInspector;
using System.Collections.Generic;
using UnityEngine;

public class SceneAndAssetsOnlyExamplesComponent : MonoBehaviour
{
    [Title("Assets only")]
    [AssetsOnly]
    public List<GameObject> OnlyPrefabs;

    [AssetsOnly]
    public GameObject SomePrefab;

    [AssetsOnly]
    public Material MaterialAsset;

    [AssetsOnly]
    public MeshRenderer SomeMeshRendererOnPrefab;

    [Title("Scene Objects only")]
    [SceneObjectsOnly]
    public List<GameObject> OnlySceneObjects;

    [SceneObjectsOnly]
    public GameObject SomeSceneObject;

    [SceneObjectsOnly]
    public MeshRenderer SomeMeshRenderer;
}

2.2 CustomValueDrawer

自定义属性的显示方式。

  • string action

    显示属性的方法名。

image-20240715004812602
  1. action 方法中写 GUI 的显示逻辑,并返回字段的值。
  2. 该特性应用于数组时,将对数组的每个元素应用一次。
  3. 使用该特性时,需要配合 UNITY_EDITOR 指令,用法如下。
// CustomValueDrawerExamplesComponent.cs

using Sirenix.OdinInspector;
using System;
using System.Collections.Generic;
using UnityEngine;

#if UNITY_EDITOR // Editor namespaces can only be used in the editor.
using Sirenix.Utilities.Editor;
using UnityEditor;
#endif

public class CustomValueDrawerExamplesComponent : MonoBehaviour
{
    public float From = 2, To = 7;

    [CustomValueDrawer("MyCustomDrawerStatic")]
    public float CustomDrawerStatic;

    [CustomValueDrawer("MyCustomDrawerInstance")]
    public float CustomDrawerInstance;

    [CustomValueDrawer("MyCustomDrawerAppendRange")]
    public float AppendRange;

    [CustomValueDrawer("MyCustomDrawerArrayNoLabel")]
    public float[] CustomDrawerArrayNoLabel = new float[] { 3f, 5f, 6f };

#if UNITY_EDITOR // Editor-related code must be excluded from builds
    private static float MyCustomDrawerStatic(float value, GUIContent label) {
        return EditorGUILayout.Slider(label, value, 0f, 10f);
    }

    private float MyCustomDrawerInstance(float value, GUIContent label) {
        return EditorGUILayout.Slider(label, value, this.From, this.To);
    }

    private float MyCustomDrawerAppendRange(float value, GUIContent label, Func<GUIContent, bool> callNextDrawer) {
        SirenixEditorGUI.BeginBox();
        callNextDrawer(label);
        var result = EditorGUILayout.Slider(value, this.From, this.To);
        SirenixEditorGUI.EndBox();
        return result;
    }

    private float MyCustomDrawerArrayNoLabel(float value) {
        return EditorGUILayout.Slider(value, this.From, this.To);
    }
#endif
}

2.3 OnValueChanged

在检查器中编辑属性时,延迟对属性应用更改。更改值时,不会应用(黄色显示)。仅更改完成后,才会应用该值。

类似于 Unity 的内置延迟属性,但此特性也可以应用于属性。

image-20240715005217404
// DelayedPropertyExampleComponent.cs

using Sirenix.OdinInspector;
using UnityEngine;

public class DelayedPropertyExampleComponent : MonoBehaviour
{
    // Delayed and DelayedProperty attributes are virtually identical...
    [Delayed]
    [OnValueChanged("OnValueChanged")]
    public int DelayedField;

    // ... but the DelayedProperty can, as the name suggests, also be applied to properties.
    [ShowInInspector, DelayedProperty]
    [OnValueChanged("OnValueChanged")]
    public string DelayedProperty { get; set; }

    private void OnValueChanged() {
        Debug.Log("Value changed!");
    }
}

2.4 DetailedInfoBox

为属性设置消息盒。

  • string message

    默认显示的信息。

  • string details

    点击后展开显示的详细信息。

  • InfoMessageType infoMessageType = InfoMessageType.Info

    消息盒种类。

  • string visibleIf = null

    如果表达式为 true,则显示,否则不显示。

image-20240715005253530
// DetailedInfoBoxExampleComponent.cs
using Sirenix.OdinInspector;
using UnityEngine;

public class DetailedInfoBoxExampleComponent : MonoBehaviour
{
    [DetailedInfoBox("Click the DetailedInfoBox...",
        "... to reveal more information!\n" +
        "This allows you to reduce unnecessary clutter in your editors, and still have all the relavant information available when required.")]
    public int Field;
}

2.5 EnableGUI

激活 GUI 交互,使得能够在 Inspector 窗口进行编辑。

image-20240715005345457
// EnableGUIExampleComponent.cs
using Sirenix.OdinInspector;
using UnityEngine;

public class EnableGUIExampleComponent : MonoBehaviour
{
    [ShowInInspector]
    public int GUIDisabledProperty { get { return 10; } }
    
    [ShowInInspector, EnableGUI]
    public int GUIEnabledProperty { get { return 10; } }
}

2.6 GUIColor

为 GUI 上色。

  • float r, float g, float b, float a = 1f

    使用 RGBA 指定颜色。

  • string getColor

    指定颜色名。

image-20240715005438314
// GUIColorExamplesComponent.cs

using Sirenix.OdinInspector;
using UnityEngine;

public class GUIColorExamplesComponent : MonoBehaviour
{
    [GUIColor(0.3f, 0.8f, 0.8f, 1f)]
    public int ColoredInt1;

    [GUIColor(0.3f, 0.8f, 0.8f, 1f)]
    public int ColoredInt2;

    [GUIColor("#FF0000")]
    public int Hex1;

    [GUIColor("#FF000077")]
    public int Hex2;

    [GUIColor("RGB(0, 1, 0)")]
    public int Rgb;

    [GUIColor("RGBA(0, 1, 0, 0.5)")]
    public int Rgba;

    [GUIColor("orange")]
    public int NamedColors;

    [ButtonGroup]
    [GUIColor(0, 1, 0)]
    private void Apply() { }

    [ButtonGroup]
    [GUIColor(1, 0.6f, 0.4f)]
    private void Cancel() { }

    [InfoBox("You can also reference a color member to dynamically change the color of a property.")]
    [GUIColor("GetButtonColor")]
    [Button("I Am Fabulous", ButtonSizes.Gigantic)]
    private static void IAmFabulous() { }

    [Button(ButtonSizes.Large)]
    [GUIColor("@Color.Lerp(Color.red, Color.green, Mathf.Abs(Mathf.Sin((float)EditorApplication.timeSinceStartup)))")]
    private static void Expressive() { }

#if UNITY_EDITOR // Editor-related code must be excluded from builds
    private static Color GetButtonColor() {
        Sirenix.Utilities.Editor.GUIHelper.RequestRepaint();
        return Color.HSVToRGB(Mathf.Cos((float)UnityEditor.EditorApplication.timeSinceStartup + 1f) * 0.225f + 0.325f, 1, 1);
    }
#endif
}

2.7 HideLabel

隐藏属性名。

image-20240715005523963
// HideLabelExamplesComponent.cs

using Sirenix.OdinInspector;
using UnityEngine;

public class HideLabelExamplesComponent : MonoBehaviour
{
    [Title("Wide Colors")]
    [HideLabel]
    [ColorPalette("Fall")]
    public Color WideColor1;

    [HideLabel]
    [ColorPalette("Fall")]
    public Color WideColor2;

    [Title("Wide Vector")]
    [HideLabel]
    public Vector3 WideVector1;

    [HideLabel]
    public Vector4 WideVector2;

    [Title("Wide String")]
    [HideLabel]
    public string WideString;

    [Title("Wide Multiline Text Field")]
    [HideLabel]
    [MultiLineProperty]
    public string WideMultilineTextField = "";
}

2.8 PropertyOrder

指定属性显示的顺序。

  • float order

    显示顺序,从小到大排列。

image-20240715005613267
// PropertyOrderExamplesComponent.cs
using Sirenix.OdinInspector;
using UnityEngine;

public class PropertyOrderExamplesComponent : MonoBehaviour
{
    [PropertyOrder(1)]
    public int Second;
    
    [InfoBox("PropertyOrder is used to change the order of properties in the inspector.")]
    [PropertyOrder(-1)]
    public int First;
}

2.9 PropertySpace

指定属性显示的间距。

  • float spaceBefore

    上间距。

  • float spaceAfter

    下间距。

image-20240715005654521
// SpaceExampleComponent.cs
using Sirenix.OdinInspector;
using UnityEngine;

public class SpaceExampleComponent : MonoBehaviour
{
    // PropertySpace and Space attributes are virtually identical.
    [Space]
    [BoxGroup("Space", ShowLabel = false)]
    public int Space;
    
    // You can also control spacing both before and after the PropertySpace attribute.
    [PropertySpace(SpaceBefore = 30, SpaceAfter = 60)]
    [BoxGroup("BeforeAndAfter", ShowLabel = false)]
    public int BeforeAndAfter;
    
    // The PropertySpace attribute can, as the name suggests, also be applied to properties.
    [PropertySpace]
    [ShowInInspector, BoxGroup("Property", ShowLabel = false)]
    public string Property { get; set; }
}

2.10 ReadOnly

只在 Inspector 窗口显示,而不能改变值。

image-20240715005738889
// ReadOnlyExamplesComponent.cs
using Sirenix.OdinInspector;
using UnityEngine;

public class ReadOnlyExamplesComponent : MonoBehaviour
{
    [ReadOnly]
    public string MyString = "This is displayed as text";
    
    [ReadOnly]
    public int MyInt = 9001;
    
    [ReadOnly]
    public int[] MyIntList = new int[] { 1, 2, 3, 4, 5, 6, 7, };
}

2.11 Required

如果对象没有关联值,则显示信息。

  • string errorMessage

    显示信息。

  • InfoMessageType messageType

    信息类型。

image-20240715005824011
// RequiredExamplesComponent.cs
using Sirenix.OdinInspector;
using UnityEngine;

public class RequiredExamplesComponent : MonoBehaviour
{
    [Required]
    public GameObject MyGameObject;
    
    [Required("Custom error message.")]
    public Rigidbody MyRigidbody;
    
    [InfoBox("Use $ to indicate a member string as message.")]
    [Required("$DynamicMessage")]
    public GameObject GameObject;
    
    public string DynamicMessage = "Dynamic error message";
}

2.12 RequiredIn(*)

说实话,看了半天没看懂。。。

image-20240715005906461
// RequiredInAttributeExamplesComponent.cs
using Sirenix.OdinInspector;
using UnityEngine;

public class RequiredInAttributeExamplesComponent : MonoBehaviour
{
    [RequiredIn(PrefabKind.InstanceInScene, ErrorMessage = "Error messages can be customized. Odin expressions is supported.")]
    public string InstanceInScene = "Instances of prefabs in scenes";
    
    [RequiredIn(PrefabKind.InstanceInPrefab)]
    public string InstanceInPrefab = "Instances of prefabs nested inside other prefabs";
    
    [RequiredIn(PrefabKind.Regular)]
    public string Regular = "Regular prefab assets";
    
    [RequiredIn(PrefabKind.Variant)]
    public string Variant = "Prefab variant assets";
    
    [RequiredIn(PrefabKind.NonPrefabInstance)]
    public string NonPrefabInstance = "Non-prefab component or gameobject instances in scenes";
    
    [RequiredIn(PrefabKind.PrefabInstance)]
    public string PrefabInstance = "Instances of regular prefabs, and prefab variants in scenes or nested in other prefabs";
    
    [RequiredIn(PrefabKind.PrefabAsset)]
    public string PrefabAsset = "Prefab assets and prefab variant assets";
    
    [RequiredIn(PrefabKind.PrefabInstanceAndNonPrefabInstance)]
    public string PrefabInstanceAndNonPrefabInstance = "Prefab Instances, as well as non-prefab instances";
}

2.13 Searchable

可查询 chiledren 的类型和名称。

  • bool FuzzySearch = true

    是否使用模糊字符串匹配进行搜索。

  • SearchFilterOptions FilterOptions = SearchFilterOptions.All

    搜索方式。

  • bool Recursive = true

    是递归搜索,还是只搜索顶级属性。

image-20240715010054683
// SearchablePerksExampleComponent.cs

using Sirenix.OdinInspector;
using System;
using System.Collections.Generic;
using UnityEngine;

public class SearchablePerksExampleComponent : MonoBehaviour
{
    [Searchable]
    public List<Perk> Perks = new List<Perk>() {
        new Perk() {
            Name = "Old Sage",
            Effects = new List<Effect>() {
                new Effect() { Skill = Skill.Wisdom, Value       = 2, },
                new Effect() { Skill = Skill.Intelligence, Value = 1, },
                new Effect() { Skill = Skill.Strength, Value     = -2 },
            },
        },
        new Perk() {
            Name = "Hardened Criminal",
            Effects = new List<Effect>() {
                new Effect() { Skill = Skill.Dexterity, Value = 2, },
                new Effect() { Skill = Skill.Strength, Value  = 1, },
                new Effect() { Skill = Skill.Charisma, Value  = -2 },
            },
        },
        new Perk() {
            Name = "Born Leader",
            Effects = new List<Effect>() {
                new Effect() { Skill = Skill.Charisma, Value     = 2, },
                new Effect() { Skill = Skill.Intelligence, Value = -3 },
            },
        },
        new Perk() {
            Name = "Village Idiot",
            Effects = new List<Effect>() {
                new Effect() { Skill = Skill.Charisma, Value     = 4, },
                new Effect() { Skill = Skill.Constitution, Value = 2, },
                new Effect() { Skill = Skill.Intelligence, Value = -3 },
                new Effect() { Skill = Skill.Wisdom, Value       = -3 },
            },
        },
    };

    [Serializable]
    public class Perk
    {
        public string Name;

        [TableList]
        public List<Effect> Effects;
    }

    [Serializable]
    public class Effect
    {
        public Skill Skill;
        public float Value;
    }

    public enum Skill
    {
        Strength,
        Dexterity,
        Constitution,
        Intelligence,
        Wisdom,
        Charisma,
    }
}

2.14 ShowInInspector

在 Inspector 窗口中显示任意成员。

注意:

​ ShowInInspector 不会序列化成员,仅使用该特性不会保存任何改动。

image-20240715010414020
// ShowPropertiesInTheInspectorExamplesComponent.cs

using Sirenix.OdinInspector;
using UnityEngine;

public class ShowPropertiesInTheInspectorExamplesComponent : MonoBehaviour
{
    [SerializeField, HideInInspector]
    private int evenNumber;

    [ShowInInspector]
    public int EvenNumber {
        get { return this.evenNumber; }
        set { this.evenNumber = value - (value % 2); }
    }
}

2.15 Title

在属性上方显示标题。

  • string title

    标题名。

  • string subtitle = null

    副标题。

  • TitleAlignments titleAlignment = TitleAlignments.Left

    对齐方式。

  • bool horizontalLine = true

    是否显示水平线。

  • bool bold = true

    标题是否加粗显示。

image-20240715010618848
// TitleExamplesComponent.cs

using Sirenix.OdinInspector;
using UnityEngine;

public class TitleExamplesComponent : MonoBehaviour
{
    [Title("Titles and Headers")]
    public string MyTitle = "My Dynamic Title";

    public string MySubtitle = "My Dynamic Subtitle";

    [Title("Static title")]
    public int C;

    public int D;

    [Title("Static title", "Static subtitle")]
    public int E;

    public int F;

    [Title("$MyTitle", "$MySubtitle")]
    public int G;

    public int H;

    [Title("Non bold title", "$MySubtitle", bold: false)]
    public int I;

    public int J;

    [Title("Non bold title", "With no line seperator", horizontalLine: false, bold: false)]
    public int K;

    public int L;

    [Title("$MyTitle", "$MySubtitle", TitleAlignments.Right)]
    public int M;

    public int N;

    [Title("$MyTitle", "$MySubtitle", TitleAlignments.Centered)]
    public int O;

    public int P;

    [Title("@DateTime.Now.ToString(\"dd:MM:yyyy\")", "@DateTime.Now.ToString(\"HH:mm:ss\")")]
    public int Expression;

    [ShowInInspector]
    [Title("Title on a Property")]
    public int S { get; set; }

    [Title("Title on a Method")]
    [Button]
    public void DoNothing() { }
}

2.16 TypeFilter

依据类型显示属性。

  • string filterGetter

    获取显示属性的方法。

image-20240715010719942
// TypeFilterExamplesComponent.cs
using Sirenix.OdinInspector;
using Sirenix.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class TypeFilterExamplesComponent : SerializedMonoBehaviour
{
    [TypeFilter("GetFilteredTypeList")]
    public BaseClass A, B;
    
    [TypeFilter("GetFilteredTypeList")]
    public BaseClass[] Array = new BaseClass[3];
    
    public IEnumerable<Type> GetFilteredTypeList()
    {
        var q = typeof(BaseClass).Assembly.GetTypes()
            .Where(x => !x.IsAbstract)                                          // Excludes BaseClass
            .Where(x => !x.IsGenericTypeDefinition)                             // Excludes C1<>
            .Where(x => typeof(BaseClass).IsAssignableFrom(x));                 // Excludes classes not inheriting from BaseClass
    
        // Adds various C1<T> type variants.
        q = q.AppendWith(typeof(C1<>).MakeGenericType(typeof(GameObject)));
        q = q.AppendWith(typeof(C1<>).MakeGenericType(typeof(AnimationCurve)));
        q = q.AppendWith(typeof(C1<>).MakeGenericType(typeof(List<float>)));
    
        return q;
    }
    
    public abstract class BaseClass
    {
        public int BaseField;
    }
    
    public class A1 : BaseClass { public int _A1; }
    public class A2 : A1 { public int _A2; }
    public class A3 : A2 { public int _A3; }
    public class B1 : BaseClass { public int _B1; }
    public class B2 : B1 { public int _B2; }
    public class B3 : B2 { public int _B3; }
    public class C1<T> : BaseClass { public T C; }
}

2.17 TypeInfoBox

在类型的每个示例顶部绘制一个信息框。

  • string message

    绘制的信息。

image-20240715010844080
// TypeInfoBoxExampleComponent.cs

using Sirenix.OdinInspector;
using System;
using UnityEngine;

#if UNITY_EDITOR // Editor namespaces can only be used in the editor.
using Sirenix.OdinInspector.Editor.Examples;
#endif

public class TypeInfoBoxExampleComponent : MonoBehaviour
{
    public MyType MyObject = new MyType();

#if UNITY_EDITOR // MyScriptyScriptableObject is an example type and only exists in the editor
    [InfoBox("Click the pen icon to open a new inspector for the Scripty object.")]
    [InlineEditor]
    public MyScriptyScriptableObject Scripty;
#endif

    [Serializable]
    [TypeInfoBox("The TypeInfoBox attribute can be put on type definitions and will result in an InfoBox being drawn at the top of a property.")]
    public class MyType
    {
        public int Value;
    }

#if UNITY_EDITOR // Editor-related code must be excluded from builds
    [OnInspectorInit]
    private void CreateData() {
        Scripty = ExampleHelper.GetScriptableObject<MyScriptyScriptableObject>("Scripty");
    }

    [OnInspectorDispose]
    private void CleanupData() {
        if (Scripty != null) UnityEngine.Object.DestroyImmediate(Scripty);
    }
#endif
}

2.18 ValidateInput

允许检查 Inspector 窗口中拖拽关联值是否正确。

  • string condition

    判断是否正确的方法。

  • string defaultMessage

    显示信息。

  • InfoMessageType messageType

    信息类型。

image-20240715011220919
// ValidateInputExamplesComponent.cs

using Sirenix.OdinInspector;
using UnityEngine;

#if UNITY_EDITOR // Editor namespaces can only be used in the editor.
using Sirenix.OdinInspector.Editor.Examples;
#endif

public class ValidateInputExamplesComponent : MonoBehaviour
{
#if UNITY_EDITOR // MyScriptyScriptableObject is an example type and only exists in the editor
    [HideLabel]
    [Title("Default message", "You can just provide a default message that is always used")]
    [ValidateInput("MustBeNull", "This field should be null.")]
    public MyScriptyScriptableObject DefaultMessage;
#endif

    [Space(12), HideLabel]
    [Title("Dynamic message", "Or the validation method can dynamically provide a custom message")]
    [ValidateInput("HasMeshRendererDynamicMessage", "Prefab must have a MeshRenderer component")]
    public GameObject DynamicMessage;

    [Space(12), HideLabel]
    [Title("Dynamic message type", "The validation method can also control the type of the message")]
    [ValidateInput("HasMeshRendererDynamicMessageAndType", "Prefab must have a MeshRenderer component")]
    public GameObject DynamicMessageAndType;

    [Space(8), HideLabel]
    [InfoBox("Change GameObject value to update message type", InfoMessageType.None)]
    public InfoMessageType MessageType;

    [Space(12), HideLabel]
    [Title("Dynamic default message", "Use $ to indicate a member string as default message")]
    [ValidateInput("AlwaysFalse", "$Message", InfoMessageType.Warning)]
    public string Message = "Dynamic ValidateInput message";

#if UNITY_EDITOR // Editor-related code must be excluded from builds
    private bool AlwaysFalse(string value) {
        return false;
    }

    private bool MustBeNull(MyScriptyScriptableObject scripty) {
        return scripty == null;
    }

    private bool HasMeshRendererDefaultMessage(GameObject gameObject) {
        if (gameObject == null) return true;

        return gameObject.GetComponentInChildren<MeshRenderer>() != null;
    }

    private bool HasMeshRendererDynamicMessage(GameObject gameObject, ref string errorMessage) {
        if (gameObject == null) return true;

        if (gameObject.GetComponentInChildren<MeshRenderer>() == null) {
            // If errorMessage is left as null, the default error message from the attribute will be used
            errorMessage = "\"" + gameObject.name + "\" must have a MeshRenderer component";

            return false;
        }

        return true;
    }

    private bool HasMeshRendererDynamicMessageAndType(GameObject gameObject, ref string errorMessage, ref InfoMessageType? messageType) {
        if (gameObject == null) return true;

        if (gameObject.GetComponentInChildren<MeshRenderer>() == null) {
            // If errorMessage is left as null, the default error message from the attribute will be used
            errorMessage = "\"" + gameObject.name + "\" should have a MeshRenderer component";

            // If messageType is left as null, the default message type from the attribute will be used
            messageType = this.MessageType;

            return false;
        }

        return true;
    }
#endif
}

2.19 ValueDropdown

创建下拉列表,以供在 Inspector 面板上选择对应的值。

  • string valuesGetter

    获取下拉列表可选值的方法。返回值可以是数组,或者 ValueDropdownList<T> 的 IEnumerable。

    ValueDropdownList 的成员为 ValueDropdownItem,其成员 Text 为显示在 Inspector 窗口上对应值 Value 的信息。

  • bool AppendNextDrawer = false

    如果为 true,则改为用小按钮开启下拉列表,而不是用宽按钮。

  • bool DisableGUIInAppendedDrawer = false

    是否可以在 Inspector 窗口上编辑值。

  • bool ExpandAllMenuItems = false

    如果为 true,则下拉菜单呈现树状图,用 ‘/’ 号表示父子关系。

  • bool DrawDropdownForListElements = true

    如果对象为列表,则需禁用此属性,以正常显示子元素。

  • bool IsUniqueList = false

    对象为列表时,其内容是否唯一,不可重复。

  • bool ExcludeExistingValuesInList = false

    如果对象为列表,且 IsUniqueList 为 true,则启用此属性将排除现有值;

    否则,将显示一个复选框,指示该项是否已包含。

image-20240715011330407
// ValueDropdownExamplesComponent.cs

using Sirenix.OdinInspector;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class ValueDropdownExamplesComponent : MonoBehaviour
{
    [ValueDropdown("TextureSizes")]
    public int SomeSize1;

    [ValueDropdown("FriendlyTextureSizes")]
    public int SomeSize2;

    [ValueDropdown("FriendlyTextureSizes", AppendNextDrawer = true, DisableGUIInAppendedDrawer = true)]
    public int SomeSize3;

    [ValueDropdown("GetListOfMonoBehaviours", AppendNextDrawer = true)]
    public MonoBehaviour SomeMonoBehaviour;

    [ValueDropdown("KeyCodes")]
    public KeyCode FilteredEnum;

    [ValueDropdown("TreeViewOfInts", ExpandAllMenuItems = true)]
    public List<int> IntTreview = new List<int>() { 1, 2, 7 };

    [ValueDropdown("GetAllSceneObjects", IsUniqueList = true)]
    public List<GameObject> UniqueGameobjectList;

    [ValueDropdown("GetAllSceneObjects", IsUniqueList = true, DropdownTitle = "Select Scene Object", DrawDropdownForListElements = false, ExcludeExistingValuesInList = true)]
    public List<GameObject> UniqueGameobjectListMode2;

#if UNITY_EDITOR        // Editor-related code must be excluded from builds
#pragma warning disable // And these members are in fact being used, though the compiler cannot tell. Let's not have bothersome warnings.
    private IEnumerable TreeViewOfInts = new ValueDropdownList<int>() {
        { "Node 1/Node 1.1", 1 },
        { "Node 1/Node 1.2", 2 },
        { "Node 2/Node 2.1", 3 },
        { "Node 3/Node 3.1", 4 },
        { "Node 3/Node 3.2", 5 },
        { "Node 1/Node 3.1/Node 3.1.1", 6 },
        { "Node 1/Node 3.1/Node 3.1.2", 7 },
    };

    private IEnumerable<MonoBehaviour> GetListOfMonoBehaviours() {
        return GameObject.FindObjectsOfType<MonoBehaviour>();
    }

    private static IEnumerable<KeyCode> KeyCodes = Enumerable.Range((int)KeyCode.Alpha0, 10).Cast<KeyCode>();

    private static IEnumerable GetAllSceneObjects() {
        Func<Transform, string> getPath = null;
        getPath = x => (x ? getPath(x.parent) + "/" + x.gameObject.name : "");
        return GameObject.FindObjectsOfType<GameObject>().Select(x => new ValueDropdownItem(getPath(x.transform), x));
    }

    private static IEnumerable GetAllScriptableObjects() {
        return UnityEditor.AssetDatabase.FindAssets("t:ScriptableObject")
                          .Select(x => UnityEditor.AssetDatabase.GUIDToAssetPath(x))
                          .Select(x => new ValueDropdownItem(x, UnityEditor.AssetDatabase.LoadAssetAtPath<ScriptableObject>(x)));
    }

    private static IEnumerable GetAllSirenixAssets() {
        var root = "Assets/Plugins/Sirenix/";

        return UnityEditor.AssetDatabase.GetAllAssetPaths()
                          .Where(x => x.StartsWith(root))
                          .Select(x => x.Substring(root.Length))
                          .Select(x => new ValueDropdownItem(x, UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(root + x)));
    }

    private static IEnumerable FriendlyTextureSizes = new ValueDropdownList<int>() {
        { "Small", 256 },
        { "Medium", 512 },
        { "Large", 1024 },
    };

    private static int[] TextureSizes = new int[] { 256, 512, 1024 };
#endif
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1926498.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Python thinker GUI界面的股票评论数据及投资者情绪分析设计与实现

1.绪论 1.1背景介绍 Python 的 Tkinter 库提供了创建用户界面的工具&#xff0c;可以用来构建股票评论数据及投资者情绪分析的图形用户界面&#xff08;GUI&#xff09;。通过该界面&#xff0c;用户可以输入股票评论数据&#xff0c;然后通过情感分析等技术对评论进行情绪分析…

昇思25天学习打卡营第14天 | ShuffleNet图像分类

昇思25天学习打卡营第14天 | ShuffleNet图像分类 文章目录 昇思25天学习打卡营第14天 | ShuffleNet图像分类ShuffleNetPointwise Group ConvolutionChannel ShuffleShuffleNet模块网络构建 模型训练与评估数据集训练模型评估模型预测 总结打卡 ShuffleNet ShuffleNetV1是旷世科…

大模型系列3--pytorch dataloader的原理

pytorch dataloader运行原理 1. 背景2. 环境搭建2.1. 安装WSL & vscode2.2. 安装conda & pytorch_gpu环境 & pytorch 2.112.3 命令行验证python环境2.4. vscode启用pytorch_cpu虚拟环境 3. 调试工具3.1. vscode 断点调试3.2. py-spy代码栈探测3.3. gdb attach3.4. …

基于锚框的物体检测过程

说明&#xff1a;基于锚框的物体检测过程&#xff1a;分为单阶段和两阶段 整体步骤&#xff1a; 提供目标候选区域&#xff1a; 锚框提供了一组预定义的候选区域&#xff0c;这些区域可以覆盖各种尺度和长宽比的目标。通过这些锚框&#xff0c;可以在不同的位置和不同的尺度上…

02-Charles的安装与配置

一、Charles的安装 Charles的下载地址&#xff1a;https://www.charlesproxy.com/。 下载之后&#xff0c;傻瓜式安装即可。 二、Charles组件介绍 主导航栏介绍&#xff1a; 请求导航栏介绍&#xff1a; 请求数据栏介绍&#xff1a; 三、Charles代理设置 四、客户端-windows代理…

【Linux】多线程_6

文章目录 九、多线程7. 生产者消费者模型生产者消费者模型的简单代码结果演示 未完待续 九、多线程 7. 生产者消费者模型 生产者消费者模型的简单代码 Makefile&#xff1a; cp:Main.ccg -o $ $^ -stdc11 -lpthread .PHONY:clean clean:rm -f cpThread.hpp&#xff1a; #i…

React学习笔记02-----

一、React简介 想实现页面的局部刷新&#xff0c;而不是整个网页的刷新。AJAXDOM可以实现局部刷新 1.特点 &#xff08;1&#xff09;虚拟DOM 开发者通过React来操作原生DOM&#xff0c;从而构建页面。 React通过虚拟DOM来实现&#xff0c;可以解决DOM的兼容性问题&#x…

NSSCTF_RE(一)暑期

[SWPUCTF 2021 新生赛]简单的逻辑 nss上附件都不对 没看明白怎么玩的 dnspy分析有三个 AchievePoint , game.Player.Bet - 22m; for (int i 0; i < Program.memory.Length; i) { byte[] array Program.memory; int num i; array[num] ^ 34; } Environment.SetEnvironment…

【CICID】GitHub-Actions-SpringBoot项目部署

[TOC] 【CICID】GitHub-Actions-SpringBoot项目部署 0 流程图 1 创建SprinBoot项目 ​ IDEA创建本地项目&#xff0c;然后推送到 Github 1.1 项目结构 1.2 Dockerfile文件 根据自身项目&#xff0c;修改 CMD ["java","-jar","/app/target/Spri…

Scrapy框架实现数据采集的详细步骤

需求描述&#xff1a; 本项目目标是使用Scrapy框架从宁波大学经济学院网站&#xff08;nbufe.edu.cn&#xff09;爬取新闻或公告详情页的内容。具体需求如下&#xff1a; 1、通过遍历多个页面&#xff08;共55页&#xff09;构建翻页URL。 2、使用scrapy自带的xpath从每页的…

STM32智能机器人避障系统教程

目录 引言环境准备智能机器人避障系统基础代码实现&#xff1a;实现智能机器人避障系统 4.1 数据采集模块 4.2 数据处理与控制模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;机器人导航与避障问题解决方案与优化收尾与总结 1. 引言 智能机器人避…

Android ImageDecoder把瘦高/扁平大图相当于fitCenter模式decode成目标小尺寸Bitmap,Kotlin

Android ImageDecoder把瘦高/扁平大图相当于fitCenter模式decode成目标小尺寸Bitmap&#xff0c;Kotlin val sz Size(MainActivity.SIZE, MainActivity.SIZE)val src ImageDecoder.createSource(mContext?.contentResolver!!, uri)val bitmap ImageDecoder.decodeBitmap(sr…

iPhone数据恢复篇:在 iPhone 上恢复找回短信的 5 种方法

方法 1&#xff1a;检查最近删除的文件夹 iOS 允许您在 30 天内恢复已删除的短信。您需要先从“设置”菜单启用“过滤器”。让我们来实际检查一下。 步骤 1&#xff1a;打开“设置” > “信息”。 步骤 2&#xff1a;选择“未知和垃圾邮件”&#xff0c;然后切换到“过滤…

全开源批量SEO外链工具html源码

全开源批量SEO外链工具html源码&#xff0c;已更新增加大量高质量外链 若需要增加修改其他外链请打开txt文件 修复优化页面端代码&#xff0c;界面布局 源码为自适应端&#xff0c;手机和电脑端都适配 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725…

Redis作为缓存,如何保证MySQL数据库与Redis缓存一致性(双写一致性)?

双写一致性&#xff1a;当修改了数据库的数据也要同时更新缓存的数据&#xff0c;缓存和数据库的数据要保持一致。 强一致性&#xff1a;如果项目要求数据库与Redis保持高度一致&#xff0c;可以采用读写锁保证强一致性。采用redisson实现的读写锁&#xff0c;在读的时候添加共…

基于单片机的停车场车位管理系统设计

1.简介 停车场车位管理系统是日常中随处可见的一种智能化车位管理技术&#xff0c;使用该技术可以提高车位管理效率&#xff0c;从而减轻人员车位管理工作负荷。本系统集成车牌识别、自动放行、自助缴费等技术&#xff0c;并且具备车位占用状态实时监测与车位数量实时统计、查询…

论文翻译:Rethinking Interpretability in the Era of Large Language Models

https://arxiv.org/abs/2402.01761 在大型语言模型时代的可解释性再思考 摘要 在过去十年中&#xff0c;随着越来越大的数据集和深度神经网络的兴起&#xff0c;可解释机器学习领域的兴趣迅速增长。同时&#xff0c;大型语言模型&#xff08;LLMs&#xff09;在广泛的任务中…

STM32-寄存器点灯案例详解

本文以PA1引脚点亮LED灯为案例&#xff0c;解析了STM32寄存器操作的配置过程&#xff0c;以及从手册查询方法和寄存器配置步骤。 一、概念 1.十六进制和二进制之间相互转换关系 首先&#xff0c;需要了解十六进制和二进制之间的基本转换方法。十六进制是一种基数为16的数制&…

如何在VS200和VScode里面查看数组全部值

如何在VS200和VScode里面查看数组全部值 如何在VS200和VScode里面查看数组全部值 如何在VS200和VScode里面查看数组全部值 需要在调试阶段&#xff0c;在监视窗口添加表达式即可 第一种是解包&#xff0c;能够从0开始查看指定元素个数 第二种是指针索引&#xff0c;能够从0开…

Dpm-tse:目标声音提取的扩散概率模型

第二章 目标说话人提取之《DPM-TSE: A DIFFUSION PROBABILISTIC MODEL FOR TARGET SOUND EXTRACTION》 文章目录 前言一、任务二、动机三、挑战四、方法1.概率扩散模型2.修正噪音时间表和采样步骤3. 模型框架4. 五、实验评价1.数据集2.消融实验3.客观评价4.主观评价 六、结论七…