Unity Odin特性解析

Odin の機能の分析

I.はじめに

Odin は Unity の非常に強力なエディター プラグインであり、エディターの表示と対話を豊かにするために使用できる多くの豊富な機能 (属性) を提供します。いくつかの便利な機能を以下に示します。

2. 機能百科事典

2.1 制限事項関連

2.1.1 [AssetsOnly] プロジェクトリソースのみ

  • 機能:
    プロジェクト配下のリソースのみ選択可能、シーン配下のリソースは選択不可
  • 例:
    [AssetsOnly]
    public GameObject SomePrefab;

2.1.2 [SceneObjectsOnly] シーンリソースのみ

  • 機能:
    シーン配下のリソースのみ選択可能、プロジェクト配下のリソースは選択不可
  • 例:
    [SceneObjectsOnly]
    public GameObject SomePrefab;

2.1.3 【MinValue】&【MaxValue】最小値と最大値

  • 機能:
    最小値と最大値を制限する
  • 例:
    [MinValue(0)] [MaxValue(5)]
    public int val;

2.1.4 【MinMaxSlider】最小値と最大値のスライダー(Vector2を修正)

  • 機能:
    最小値と最大値も制限しますが、スクロール バーがあります。Vector2 を変更するために使用されます
  • 例:
    [MinMaxSlider(-10, 10)]
    public Vector2 MinMaxValueSlider = new Vector2(-7, -2);
  • レンダリング:
    ここに画像の説明を挿入

2.1.5 [Range] & [PropertyRange] フィールドとプロパティ範囲

  • 機能:
    Range はフィールドの範囲を制限するために使用されます。PropertyRange
    はより強力で、プロパティの範囲も制限できます。Unity の通常の組み込み関数ではフィールドを表示できません。ここでは Odin の [ShowInInspector] 機能を使用して Property プロパティを表示します

  • 例:
    [Range(0, 10)]
    public int フィールド = 2;

    [ShowInInspector,PropertyRange(0, 10)]
    public int Property { get; 設定; }

  • レンダリング:
    ここに画像の説明を挿入

  • 高度な使用法:
    上記の最小値と最大値はすべて固定値ですが、実際には、次の例のように、動的フィールド値を範囲として使用することもできます。

  • 高度な例:
    [PropertyRange(0, “Max”)]
    public int Dynamic = 6;

    public int Max = 100;

2.1.6 [必須] 制限されたリソースを空にすることはできません

  • 機能:
    Required を使用して、リソースを空にできないことを制限できます。

  • 構文:
    [Required("リソースが空の場合はプロンプトを表示します。空白のままでも構いません")]

  • 例:
    [必須]
    public GameObject MyGameObject;

    [Required(“カスタム エラー メッセージ。”)]
    public Rigidbody MyRigidbody;

  • レンダリング:
    -

2.1.7 【ValidateInput】代入検証

  • 関数:
    ValidateInput は非常に実用的な関数で、ユーザーがフィールドに値を割り当てると、コールバック メソッドがトリガーされます。その後、ユーザーが割り当てたエンティティをチェックするコード ロジックを作成できます。チェックが失敗した場合は、リマインダーを与えることができます

  • 構文:
    [ValidateInput("コールバック メソッド名", "デフォルト プロンプト")]

[ValidateInput("HasMeshRendererDynamicMessageAndType", "Prefab must have a MeshRenderer component")]
public GameObject DynamicMessageAndType;
 
//返回类型为bool,表示是否通过检测
private bool HasMeshRendererDynamicMessageAndType(GameObject gameObject, ref string errorMessage, ref InfoMessageType? messageType)
    {
    	//没有赋值时,通过检测
        if (gameObject == null) return true;

		//如果赋值的GameObject没有MeshRenderer,return false检测不通过
        if (gameObject.GetComponentInChildren<MeshRenderer>() == null)
        {
            // 设置提示信息
            errorMessage = "\"" + gameObject.name + "\" should have a MeshRenderer component";

            // //设置警告类型
            messageType = InfoMessageType.Warning; 

            return false;
        }

        return true;
    }

2.1.8 【TypeFilter】制限タイプ

  • 機能:
    TypeFilter を使用して、指定した型コレクションのみが選択されるように制限できます
    [ShowInInspector]
    [TypeFilter("GetFilteredTypeList")]
    public BaseClass A, B;

    [ShowInInspector]
    [TypeFilter("GetFilteredTypeList")]
    public BaseClass[] Array = new BaseClass[3];

    public IEnumerable<Type> GetFilteredTypeList()
    {
        var q = typeof(BaseClass).Assembly.GetTypes()
            .Where(x => !x.IsAbstract)                                          // 排除 BaseClass
            .Where(x => !x.IsGenericTypeDefinition)                             // 排除 泛型,如C1<>
            .Where(x => typeof(BaseClass).IsAssignableFrom(x));                 // 排除没有继承BaseClass的类型

        // 增加特定的类
        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.1.9 [ReadOnly] 読み取り専用

  • 機能:
    ReadOnly を使用すると、パネルに表示されるプロパティを変更できなくなります。

  • 例:
    [ReadOnly]
    public string MyString = “これはテキストとして表示されます”;

    [読み取り専用]
    public int MyInt = 9001;

    [ReadOnly]
    public int[] MyIntList = new int[] { 1, 2, 3, 4, 5, 6, 7, };

  • レンダリング:
    ここに画像の説明を挿入

2.2 通用特性

ここでは、便利だが分類するのが難しい機能をいくつか紹介します。

2.2.1 インスペクターパネルに表示される「ShowInInspector」

  • 機能:
    ShowInInspector は、パネルのインスペクターに表示できない属性、静的変数、その他のフィールドを表示できます。とても便利な機能

  • 例:
    [ShowInInspector]
    public string DelayedProperty { get; 設定; }

    [ShowInInspector]
    public static string testStr;

  • レンダリング:
    ここに画像の説明を挿入

2.2.2 [OnValueChanged] 値変更コールバック

  • 機能:
    OnValueChanged は、フィールドの値が変更された後にコールバック メソッドを呼び出すことができます。

  • 構文:
    [OnValueChanged("コールバックメソッド名")]

  • 例:
    [OnValueChanged(“OnValueChanged”)]
    public int val;

    private void OnValueChanged()
    { Debug.Log(“値が変更されました!”); }

  • レンダリング:
    ここに画像の説明を挿入

2.2.3 【Delayed】&【DelayedProperty】遅延

  • 機能:
    Delayed および DelayedProperty は上記の OnValueChanged とともに使用できます。OnValueChanged は値が変更された後にコールバックできますが、値が変更されるたびにコールバックされます。このとき Delayed が便利で、値の変更が完了してからコールバックできるのでコールバックが少なくなります。Delayed は共通フィールドを変更し、DelayedProperty を使用してプロパティを変更できます

  • 例:

    [遅延]
    [OnValueChanged(“OnValueChanged”)]
    public int DelayedField;

    [ShowInInspector, DelayedProperty]
    [OnValueChanged(“OnValueChanged”)]
    public string DelayedProperty { get; 設定; }

    private void OnValueChanged()
    { Debug.Log(“値が変更されました!”); }

  • レンダリング:
    ここに画像の説明を挿入

2.2.4 [GUIColor]色の変更

  • 機能:
    GUIColor はフィールド、ボタン、色のグラデーションの色を変更できます。次に、公式の例を見てみましょう
  • 例:
    [GUIColor(0.3f, 0.8f, 0.8f, 1f)]
    public int ColoredInt1;

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

    [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()
    {
    }

    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);
    }
  • レンダリング:
    ここに画像の説明を挿入

2.2.4 [ColorPalette]カラーパレット

さて、色といえば、やはり便利な機能であるカラーパレットについてお話しましょう。なぜなら、ゲームは基本的に3~4色のメインカラーで形成されるからです。これらの色をパレットに入れておくと失敗がなくなり、色選びが便利になります

  • 機能:
    ColorPalette は Color フィールドを変更するために使用され、ユーザーが色を選択できるようにその横にパレットをリストできます。

  • 構文:
    [ColorPalette] ドロップダウン ボックスで任意のパレットを選択し、パレットの下で色を選択できます。

    [ColorPalette("Palette Name")]はパレット名を指定できるので、パレットの色が直接表示されます。

  • 例:
    //パレット名は指定しないでください
    [ColorPalette]
    public Color ColorOptions;

    //スペースを追加します。そうしないと、混雑しすぎて説明が難しくなります
    [PropertySpace(SpaceBefore = 60)]

    パレット名を Underwater
    [ColorPalette(“Underwater”)]
    public Color UnderwaterColor;として指定します。

  • レンダリング:
    ここに画像の説明を挿入

2.2.5 [Title] & [HideLabel] タイトルを追加&フィールド名を非表示

  • 機能:
    Title はタイトルを追加するために使用でき、HideLabel はフィールド名を非表示にするために使用できます。

  • 例:
    [Title(“ワイドカラー”)]
    [HideLabel]
    [ColorPalette(“Fall”)]
    public Color WideColor1;

  • 効果画像:
    元のフィールド名が非表示になり、定義したタイトルとパレットのみが表示されていることがわかります。

2.2.6 [DisplayAsString]の表示内容

  • 機能:
    DisplayAsString は、文字列フィールドの内容をインスペクター パネルに表示できます。
  • 例:
    [HideLabel]
    [DisplayAsString]
    public string Title = “満足です”;
  • 効果画像:
    フィールド名は非表示ですが、フィールドの内容は表示されていることがわかります。
    ここに画像の説明を挿入

2.2.7 【PropertyOrder】フィールドの優先度

  • 機能:
    PropertyOrder はフィールドの優先順位を制御できます。優先順位の値が小さいほど、ランキングが高くなります。

  • 例:
    [PropertyOrder(1)]
    public int Second;

    [PropertyOrder(-1)]
    public int First;

  • レンダリング:
    ここに画像の説明を挿入

2.2.7 [PropertySpace]フィールドの間隔

  • 機能:
    PropertySpace はフィールド間隔の設定に使用できます。PropertySpace はカラー パレットについて説明するときに使用されました。

  • 例:
    public int スペース;

    [PropertySpace(SpaceBefore = 10, SpaceAfter = 20)]
    public int Space2;

    パブリック int スペース 3;

  • 効果画像:
    効果画像を見れば一目瞭然
    ここに画像の説明を挿入

2.2.8 【検索可能】検索

  • 機能:
    Searchable を使用してクラスやリストをマークすると、フィールド名または内容が入力内容と一致する項目を検索するための検索ボックスが表示されます。公式の例を見てみましょう
  • 例:
    [Searchable]
    public ExampleClass searchableClass = new ExampleClass();
    

    [Serializable]
    public class ExampleClass
    {
        public string SomeString = "Saehrimnir is a tasty delicacy";
        public int SomeInt = 13579;

        public DataContainer DataContainerOne = new DataContainer() { Name = "Example Data Set One" };
        public DataContainer DataContainerTwo = new DataContainer() { Name = "Example Data Set Two" };
    }

    [Serializable, Searchable] // You can also apply it on a type like this, and it will become searchable wherever it appears
    public class DataContainer
    {
        public string Name;
        public List<ExampleStruct> Data = new List<ExampleStruct>(Enumerable.Range(1, 10).Select(i => new ExampleStruct(i)));
    }

    [Serializable]
    public struct FilterableBySquareStruct : ISearchFilterable
    {
        public int Number;

        [ShowInInspector, DisplayAsString, EnableGUI]
        public int Square { get { return this.Number * this.Number; } }

        public FilterableBySquareStruct(int nr)
        {
            this.Number = nr;
        }

        public bool IsMatch(string searchString)
        {
            return searchString.Contains(Square.ToString());
        }
    }

    [Serializable]
    public struct ExampleStruct
    {
        public string Name;
        public int Number;
        public ExampleEnum Enum;

        public ExampleStruct(int nr) : this()
        {
            this.Name = "Element " + nr;
            this.Number = nr;

            this.Enum = (ExampleEnum)ExampleHelper.RandomInt(0, 5);
        }
    }

    public enum ExampleEnum
    {
        One, Two, Three, Four, Five
    }

  • レンダリング:
    画像の説明を追加してください

2.2.9 [MultiLineProperty] 複数行入力ボックス

  • 機能:
    MultiLineProperty を使用して文字列フィールドとプロパティを変更し、テキスト入力ボックスが指定された行数になるようにすることができます。

  • 例:
    [Multiline(10)]
    public string UnityMultilineField = “”;

    [InfoBox(“Odin はプロパティをサポートしていますが、Unity 独自の Multiline 属性はフィールドでのみ機能します。”)]
    [ShowInInspector]
    [MultiLineProperty(10)]
    public string OdinMultilineProperty { get; 設定; }

  • 効果の図:
    入力ボックスが 10 行あることがわかります。MultiLineProperty はプロパティを変更できますが、組み込みの MultiLine は変更できません。
    ここに画像の説明を挿入

2.2.10 [EnumPaging] 列挙型ページング

  • 機能:
    EnumPaging を使用して列挙フィールドと属性を変更できるため、列挙に左右の切り替えボタンを追加できます。

  • 例:
    [EnumPaging] public SomeEnum SomeEnumField;

    パブリック列挙型 SomeEnum
    { A、B、C }



  • レンダリング:
    画像の説明を追加してください

2.2.11 [EnumToggleButtons] 列挙ドロップダウン ボックスを水平レイアウトに

  • 機能:
    EnumToggleButtons は、列挙の元のドロップダウン ボックスを削除し、代わりに水平レイアウトの形式ですべてのオプションをリストできます。
  • 例:
    //不加修饰的枚举
    public SomeEnum OriginSomeEnum;
    
    //去掉下拉框,把枚举选项横向排列显示出来
    [EnumToggleButtons] 
    public SomeEnum SomeEnumField;

    public enum SomeEnum
    {
        First,
        Second,
        Third,
        Fourth,
        AndSoOn
    }
  • レンダリング:
    画像の説明を追加してください

2.2.12 [SuffixLabel] ラベルにサフィックスを追加します

  • 機能:
    SuffixLabel は入力ボックスの末尾にサフィックスを追加できるため、ツールを使用する人は現在の単位が何であるかを知ることができます。

  • 例:
    [SuffixLabel(“ms”, Overlay = false)]
    public float Speed1;

    //オーバーレイはサフィックスが入力ボックスにあるかどうかを示します
    [SuffixLabel("ms", Overlay = true)]
    public float Speed2;

  • レンダリング:
    ここに画像の説明を挿入

2.2.13 [InlineButton] 最後にボタンを追加します

  • 機能:
    InlineButton フィールドを変更します。フィールドの最後にボタンを追加できます。
  • 構文:
    [InlineButton("メソッド名", "ボタン名")]
    ボタン名は空でもかまいません。空の場合は、ボタンにメソッド名を付けます。
  • 例:
    [InlineButton("A")]
    public int InlineButton;
    
    [InlineButton("A")]
    [InlineButton("B", "Custom Button Name")]
    public int ChainedButtons;

    private void A()
    {
        Debug.Log("A");
    }

    private void B()
    {
        Debug.Log("B");
    }
  • レンダリング:
    ここに画像の説明を挿入

2.3 その他の特別な機能

「その他の特別な機能」とは何ですか、また「一般的な機能」との違いは何ですか。私の感覚でここに分類したのかもしれませんが、上にたくさん挙げてしまったので、新たなグループに入れないといけないような気がするのかもしれません…。

2.3.1 [ボタン]ボタン

  • 機能:
    ボタンはメソッドを変更するために使用されます。ボタンがインスペクター ウィンドウに表示され、クリックした後にメソッドのロジックが実行されます。

  • 例:
    [Button(“Hello”)]
    private void DefaultSizedButton()
    { Debug.Log(“Hello”); }

    [Button(“こんにちは〜ドラえもん”,buttonSize:ButtonSizes.Large),GUIColor(0,1,0)]
    private void Button2()
    { Debug.Log(“こんにちは〜ドラえもん”); }

  • レンダリング:
    ここに画像の説明を挿入

2.3.2 [FilePath] ファイルを選択

  • 機能:
    FilePath はファイル ウィンドウを開いてファイルを選択できます。名前を複製するのは簡単なようですが、完全な名前空間は次のとおりです: [Sirenix.OdinInspector.FilePath]、名前を複製するときに指定できます。

  • 例:
    //デフォルトで相対パスを返します
    [FilePath]
    public string UnityProjectPath;

    //開くディレクトリを指定し (ディレクトリへの相対パスが返されます)、ファイル形式を指定し、フルパスを返すかどうかを指定できます。デフォルトは false、つまり相対パス [FilePath(ParentFolder) = "Assets/OdinLearn"、
    拡張機能 = "cs "、AbsolutePath = true)]
    パブリック文字列 ResourcePath;

  • レンダリング:
    ここに画像の説明を挿入
    ここに画像の説明を挿入

2.3.3 【FolderPath】フォルダを選択

FolderPath の使用法は、フォルダーが選択されていることと、上でファイルが選択されていることを除いて、上記の FilePath と似ています。

2.3.4 [OnInspectorInit] インスペクター初期化コールバック

  • 関数:
    インスペクターがコールバックを初期化するときに OnInspectorInit を呼び出すことができます
  • 例:
    //在Inspector窗口初始化绘制
    [OnInspectorInit("@TimeFoldoutWasOpened = DateTime.Now.ToString()")]
    public string TimeFoldoutWasOpened;
  • レンダリング:
    ここに画像の説明を挿入

2.3.5 [OnInspectorGUI] インスペクターがアクティブになったときに常にコールバックする

  • 機能:
    OnInspectorGUI は、インスペクター ウィンドウがアクティブ化されたときにいつでもコールバックできます。フィールドは変更でき、メソッドも変更できます。UI を追加するために使用できます
  • 例:
    //修饰字段
    [OnInspectorInit("@Texture = EditorIcons.OdinInspectorLogo")]
    [OnInspectorGUI("DrawPreview", append: true)]//append = true,表示回调方法DrawPreview在该字段绘制之后,再调用;false,则表示在原始绘制之前
    public Texture2D Texture;
	
	//把选择的图标再绘制一遍出来
    private void DrawPreview()
    {
        if (this.Texture == null) return;

        GUILayout.BeginVertical(GUI.skin.box);
        GUILayout.Label(this.Texture);
        GUILayout.EndVertical();
    }
    
    
    //修饰方法,直接绘制
    [OnInspectorGUI]
    private void OnInspectorGUI()
    {
        UnityEditor.EditorGUILayout.HelpBox("OnInspectorGUI can also be used on both methods and properties", UnityEditor.MessageType.Info);
    }
  • レンダリング:
    ここに画像の説明を挿入

2.3.6 [OnStateUpdate] フレームごとのコールバック

  • 関数:
    OnStateUpdate フレームごとにコールバックし、フィールドを変更し、いくつかのメソッドを実行できます。
  • 例:
    public List<string> list;

    [OnStateUpdate("@#(list).State.Expanded = $value")]
    public bool ExpandList;

    [OnStateUpdate("@UnityEngine.Debug.Log(\"OnStateUpdate event invoked!\")")]
    public bool Test;
  • エフェクト画像:
    いいえ

2.3.7 【CustomValueDrawer】カスタム描画

  • 機能:
    CustomValueDrawer はフィールドを装飾し、元の描画メソッドをカスタム描画メソッドに変更できます。
  • 構文:
    CustomValueDrawer("メソッド名")
  • 例:
    //原始
    public float From = 2, To = 7;
    
    //自定义显示字段1
    [CustomValueDrawer("MyCustomDrawerStatic")]
    public float CustomDrawerStatic;
    
    //自定义显示方法1,使用固定值
    private static float MyCustomDrawerStatic(float value, GUIContent label)
    {
        return EditorGUILayout.Slider(label, value, 0f, 10f);
    }
    

    //自定义显示字段2
    [CustomValueDrawer("MyCustomDrawerInstance")]
    public float CustomDrawerInstance;
    
    //自定义显示方法2,使用From & To 作为变量
    private float MyCustomDrawerInstance(float value, GUIContent label)
    {
        return EditorGUILayout.Slider(label, value, this.From, this.To);
    }

    //自定义显示字段3
    [CustomValueDrawer("MyCustomDrawerAppendRange")]
    public float AppendRange;
    
    //自定义显示方法3,增加盒子和Label
    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;
    }
    
    //自定义显示字段4,修饰数组
    [CustomValueDrawer("MyCustomDrawerArrayNoLabel")]
    public float[] CustomDrawerArrayNoLabel = new float[] { 3f, 5f, 6f };
    
    //自定义显示方法4,去掉Label
    private float MyCustomDrawerArrayNoLabel(float value)
    {
        return EditorGUILayout.Slider(value, this.From, this.To);
    }
  • レンダリング:
    ここに画像の説明を挿入

2.4 グループグループ

2.4.1 [BoxGroup]ボックスグループ

  • 機能:
    BoxGroup はボックス内に同じグループのフィールドを作成できます

  • 例:
    // タイトル付きのボックス。
    [BoxGroup(“何らかのタイトル”)]
    パブリック文字列 A;

    [BoxGroup(“何らかのタイトル”)]
    パブリック文字列 B;

    // タイトルが中央に配置されたボックス。
    [BoxGroup(“中央揃えのタイトル”, centerLabel: true)]
    public string C;

    [BoxGroup(“中央揃えのタイトル”)]
    パブリック文字列 D;

  • レンダリング:
    ここに画像の説明を挿入

2.4.1 [horizo​​ntalGroup] 水平レイアウトグループ

  • 機能:
    horizo​​ntalGroup はフィールドを水平に配置できます
  • 例:
// LabelWidth can be helpfull when dealing with HorizontalGroups.
    [HorizontalGroup("Group 1", LabelWidth = 20)]
    public int C;

    [HorizontalGroup("Group 1")]
    public int D;

    [HorizontalGroup("Group 1")]
    public int E;

// Having multiple properties in a column can be achived using multiple groups. Checkout the "Combining Group Attributes" example.
    [HorizontalGroup("Split", 0.5f, LabelWidth = 20)]
    [BoxGroup("Split/Left")]
    public int L;

    [BoxGroup("Split/Right")]
    public int M;

    [BoxGroup("Split/Left")]
    public int N;

    [BoxGroup("Split/Right")]
    public int O;
  • レンダリング:
    ここに画像の説明を挿入

2.4.2 【VerticalGroup】数値レイアウトグループ

  • 機能:
    VerticalGroupはhorizo​​ntalGroupに似ており、垂直レイアウトを実現します。

  • 例:
    [horizo​​ntalGroup(“Split”)]
    [VerticalGroup(“Split/Left”)]
    public InfoMessageType First;

    [VerticalGroup(“Split/Left”)]
    public InfoMessageType Second;

    [HideLabel]
    [VerticalGroup(“分割/右”)]
    public int A;

    [HideLabel]
    [VerticalGroup(“分割/右”)]
    public int B;

  • レンダリング:
    ここに画像の説明を挿入

2.4.3 [ButtonGroup]ボタングループ

  • 機能:
    ButtonGroup はメソッドを変更します。これにより、同じグループのメソッド ボタンがきちんとした horizo​​ntalGroup 水平レイアウトに配置されます。
    注: Modification は horizo​​ntalGroup とは異なる方法です。
  • 例:
    //不带组名字的一个组
    [ButtonGroup]
    private void A()
    {
    }

    [ButtonGroup]
    private void B()
    {
    }

    [ButtonGroup]
    private void C()
    {
    }

    [ButtonGroup]
    private void D()
    {
    }
    

    //带组名字的一个组
    [Button(ButtonSizes.Large)]
    [ButtonGroup("Button Group1")]
    private void E()
    {
    }

    [GUIColor(0, 1, 0)]
    [ButtonGroup("Button Group1")]
    private void F()
    {
    }

  • レンダリング:
    ここに画像の説明を挿入

2.4.4 [ResponsiveButtonGroup] 折りたたみ可能なグループ

  • 関数:
    ResponsiveButtonGroup はメソッドの装飾にも使用されますが、流動的なレイアウト、左から右への水平レイアウト、およびいっぱいになったときにレイアウトを継続するために上から下へ折り返すことを使用します。
  • 例:
    [OnInspectorGUI]
    private void Space1()
    {
        GUILayout.Space(20);
    }

    [ResponsiveButtonGroup]
    public void Foo()
    {
    }

    [ResponsiveButtonGroup]
    public void Bar()
    {
    }

    [ResponsiveButtonGroup]
    public void Baz()
    {
    }

    [OnInspectorGUI]
    private void Space2()
    {
        GUILayout.Space(20);
    }

    [ResponsiveButtonGroup("UniformGroup", UniformLayout = true)]
    public void Foo1()
    {
    }

    [ResponsiveButtonGroup("UniformGroup")]
    public void Foo2()
    {
    }

    [ResponsiveButtonGroup("UniformGroup")]
    public void LongesNameWins()
    {
    }

    [ResponsiveButtonGroup("UniformGroup")]
    public void Foo4()
    {
    }

    [ResponsiveButtonGroup("UniformGroup")]
    public void Foo5()
    {
    }

    [ResponsiveButtonGroup("UniformGroup")]
    public void Foo6()
    {
    }

    [OnInspectorGUI]
    private void Space3()
    {
        GUILayout.Space(20);
    }

    [ResponsiveButtonGroup("DefaultButtonSize", DefaultButtonSize = ButtonSizes.Small)]
    public void Bar1()
    {
    }

    [ResponsiveButtonGroup("DefaultButtonSize")]
    public void Bar2()
    {
    }

    [ResponsiveButtonGroup("DefaultButtonSize")]
    public void Bar3()
    {
    }

    [Button(ButtonSizes.Large), ResponsiveButtonGroup("DefaultButtonSize")]
    public void Bar4()
    {
    }

    [Button(ButtonSizes.Large), ResponsiveButtonGroup("DefaultButtonSize")]
    public void Bar5()
    {
    }

    [ResponsiveButtonGroup("DefaultButtonSize")]
    public void Bar6()
    {
    }
  • レンダリング:
    ここに画像の説明を挿入

2.4.5 【FoldoutGroup】折りたたみ可能なグループ

  • 機能:
    FoldoutGroup は同じグループのフィールドを折りたたむことができます
  • 例:
    //Group 1
    [FoldoutGroup("Group 1")]
    public int A;

    [FoldoutGroup("Group 1")]
    public int B;

    [FoldoutGroup("Group 1")]
    public int C;
    
    //Collapsed group,默认不展开
    [FoldoutGroup("Collapsed group", expanded: false)]
    public int D;

    [FoldoutGroup("Collapsed group")]
    public int E;
    
    //使用‘$GroupTitle’字段的内容作为组名字,默认展开
    [FoldoutGroup("$GroupTitle", expanded: true)]
    public int One;

    [FoldoutGroup("$GroupTitle")]
    public int Two;

    public string GroupTitle = "Dynamic group title";
  • レンダリング:
    画像の説明を追加してください

2.4.6 [TabGroup]タブグループ

  • 機能:
    TabGroup には 2 つの重要なフィールドが含まれています: GroupName (グループ名) と TabName (ページ署名)、
    GroupName グループと一緒にタブを形成し、限られたスペースで大容量を表示するために切り替えることができます。

  • 構文:
    GroupName はコントロール "" に相当する 1 つのパラメーターが、同じタブ グループに割り当てられます
    [TabGroup("TabName page Signature")]

    2 つのパラメーター、GroupName を指定できます。同じグループが同じタブ グループに割り当てられます
    [TabGroup("GroupName グループ名", "TabName ページ署名")]

  • 例:

    [TabGroup("Tab A")]
    public int One;

    [TabGroup("Tab A")]
    public int Two;

    [TabGroup("Tab A")]
    public int Three;

    [TabGroup("Tab B")]
    public string MyString;

    [TabGroup("Tab B")]
    public float MyFloat;

    [TabGroup("Tab C")]
    [HideLabel]
    public MyTabObject TabC;

    [TabGroup("New Group", "Tab A")]
    public int A;

    [TabGroup("New Group", "Tab A")]
    public int B;

    [TabGroup("New Group", "Tab A")]
    public int C;

    [TabGroup("New Group", "Tab B")]
    public string D;

    [TabGroup("New Group", "Tab B")]
    public float E;

    [TabGroup("New Group", "Tab C")]
    [HideLabel]
    public MyTabObject F;

    [Serializable]
    public class MyTabObject
    {
        public int A;
        public int B;
        public int C;
    }
  • レンダリング:
    画像の説明を追加してください

2.5 コレクションコレクター

2.5.1 [TableList] リスト/配列レンダラー

  • 機能:
    TableList はリストと配列のレンダリングに使用でき、TableColumnWidth や HideInTables などのプロパティとともに使用できます。
  • 例:
    // ShowIndexLabels是否显示序号,默认不显示
    // DrawScrollView显示滑动条
    // MaxScrollViewHeight 当高度高于多少时开始出现滚动条
    [TableList(ShowIndexLabels = true,DrawScrollView = true, MaxScrollViewHeight = 200)]
    public List<CustomItem> List = new List<CustomItem>()
    {
        new CustomItem(),
        new CustomItem(),
        new CustomItem(),
    };

    [Serializable]
    public class CustomItem
    {    
        //指定宽度
        [PreviewField(Height = 20)]
        [TableColumnWidth(30, Resizable = false)]
        public Texture2D Icon;

        //指定宽度
        [TableColumnWidth(60)]
        public int ID;
        
        //隐藏该列
        [HideInTables]
        public string Name;
        
        //图标默认值
        [OnInspectorInit]
        private void CreateData()
        {
            Icon = ExampleHelper.GetTexture();
        }
    }
  • レンダリング図:
    TableColumnWidth、HideInTables、および TableList 独自のフィールドの構成を使用して、リストのレンダリングを定義します。
    ここに画像の説明を挿入

2.5.2 [値ドロップダウン]ドロップダウンボックス

  • 機能:
    ValueDropdown を使用してドロップダウン ボックスを表示できます。
  • 構文:
    [ValueDropdown("メソッド名")]、フィールドを変更します
  • 例:
    // 普通下路框
    [ValueDropdown("TextureSizes")] 
    public int SomeSize1;
    
    private static int[] TextureSizes = new int[] {256, 512, 1024};

    // 下拉框是string描述,值是int的下拉框
    [ValueDropdown("FriendlyTextureSizes")]
    public int SomeSize2;

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

    //下拉框是某个目录下的GameObject集合
    [ValueDropdown("GetAllSirenixAssets", IsUniqueList = true)]
    public List<GameObject> UniqueGameobjectList;

    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)));
    }

    //下拉框是树形控件
    [ValueDropdown("TreeViewOfInts", ExpandAllMenuItems = true)]
    public List<int> IntTreview = new List<int>() {1, 2, 7};

    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},
    };
  • レンダリング:
    ここに画像の説明を挿入

2.6 条件付き条件

2.6.1 DisableIf/EnableIf/ShowIf/HideIf

  • 機能:
    上記の機能の使用方法は似ており、名前から目的を推測できます。ここでは、例として DisableIf を取り上げます。DisableIf はフィールドを変更し、条件が満たされると、変更されたフィールドを無効にすることができ、変更できなくなります。
  • 例:
    public UnityEngine.Object SomeObject;

    [EnumToggleButtons]
    public InfoMessageType SomeEnum;

    public bool IsToggled;
    
    //1. 根据bool值
    //当IsToggled = true;此字段Disable
    [DisableIf("IsToggled")] [ShowIf()()]
    public int DisableIfToggled;

    //2. 根据枚举值
    //当枚举 SomeEnum = InfoMessageType.Info;此字段Disable
    [DisableIf("SomeEnum", InfoMessageType.Info)]
    public Vector2 Info;

    //当枚举 SomeEnum = InfoMessageType.Error;此字段Disable
    [DisableIf("SomeEnum", InfoMessageType.Error)]
    public Vector2 Error;


    
    //3. 根据GameObject
    //当GameObject SomeObject != null; 此字段Disable
    [DisableIf("SomeObject")]
    public Vector3 EnabledWhenNull;
    
    //4. 根据表达式
    [DisableIf("@this.IsToggled && this.SomeObject != null || this.SomeEnum == InfoMessageType.Error")]
    public int DisableWithExpression;
  • レンダリング:
    画像の説明を追加してください

2.6.2 DisableInEditorMode/DisableInPlayMode

  • 機能:
    DisableInEditorMode と DisableInPlayMode は、それぞれエディターとラックのフィールドを無効にします。
  • 例:
    [Title("Disabled in edit mode")]
    [DisableInEditorMode]
    public GameObject A;

    [DisableInPlayMode] 
    public Material B;
  • レンダリング:
    現在エディター モードです
    ここに画像の説明を挿入

おすすめ

転載: blog.csdn.net/aaa27987/article/details/131342023