Full feature introduction of Unity editor extension Odin Inspector


Introduction

Odin is already very famous and loved by many developers. It is also widely purchased on AssetStore. It is a very easy-to-use Unity editor extension plug-in. Its many features can make our Inspector panel more intuitive and easy to use. use.

This introduction is Odin version 3.0.8.0, which is all the features and functions of the latest version.

Please add image description

first part

1.AssetsOnly / SceneObjectsOnly

Marked on the properties of the object, it is used to limit the source of the object. Those marked with AssetsOnly can only be taken from the resource directory, whereas those marked with SceneObjectsOnly can only be taken from the scene. The code is as follows

    [AssetsOnly]
    public GameObject assetObject;
    [SceneObjectsOnly]
    public GameObject sceneObject;

2.CustomValueDrawer

Using a custom static method to draw properties is not very common

    [CustomValueDrawer("MyCustomDrawerStatic")]
    public float CustomTest;
    private static float MyCustomDrawerStatic(float value,GUIContent label)
    {
    
    
        return EditorGUILayout.Slider(label,value,0,10);
    }

3.DelayedProperty

Delayed assignment is a method that will trigger value changes after losing focus. It will not be triggered when dragging and adjusting. This is quite convenient to use, a bit like Finish of InputField.

    [Delayed]
    public int DelayValue;
    [ShowInInspector,DelayedProperty]
    public int DelayProperty {
    
     get; set; }

4.DetailedInfoBox

A collapsible detailed information description box used to describe the role of parameters exposed on the Inspector. Not used often

    [DetailedInfoBox("敌人攻击力","敌人每次普通攻击造成的伤害")]
    public int enemyAttack;

animated cover

5.EnableGUI

Activate attributes, but they are still limited by attribute modifiers, and I don’t use them very much.

    [ShowInInspector]
    public int DisableProp1 {
    
     get; }
    [ShowInInspector,EnableGUI]
    public int DisableProp2 {
    
     get;}
    [ShowInInspector, EnableGUI]
    public int DisableProp3 {
    
     get; set; }

animated cover

6.GUIColor

Change the color. This is very commonly used. You can change the color of the attributes. It is used for classification and prompts. It is perfect.

    [GUIColor(.5f, 1, 0, 1)]
    public int health;
    [GUIColor(0, .5f, 1f, 1)]
    public int power;
    [GUIColor(1, .5f, 0, 1)]
    public int attack;

7.HideLable

Hide labels, occasionally used, I usually use it together with "LabelText"

    [HideLabel][LabelText("玩家ID")]
    public string PlayerId;

8.PropertyOrder

Forcibly adjusting the display order of attributes is also quite useful.

    [PropertyOrder(2)]
    public string player2Name;
    [PropertyOrder(1)]
    public string player1Name;

9.PropertySpace

Attribute spacing is equivalent to the line spacing in typesetting. It is more effective for dividing different types of attributes.

    public string TypeA1, TypeA2, TypeA3;
    [PropertySpace]
    public string TypeB1;
    public string TypeB2;

10.ReadOnly

Read-only attributes are used to display some attributes that do not want to be modified. They are used for viewing or testing. I often use

    [ReadOnly]
    public string player1Name="KDF";
    public string player2Name="KKK";

11.Required

Demand, strong reminder, there will be no error message, I usually don't use it, it's a bit uncomfortable to see the error message. .

    [Required]
    public string MessageId;

animated cover

12.Searchable

Searchable, easy to use! ! ! , when there is a lot of data managed in the list, you can quickly search and operate conveniently.

    [Searchable]
    public List<SearchItem> itemList;
    [Serializable]
    public class SearchItem
    {
    
    
        public string Id;
        public string Name;
        public int Age;
    }

animated cover

13.ShowInInspector

Forced display, you can display attributes on the panel, which has been used above

14.Title

The title is the title

    [Title("基础属性")]
    public string Health;
    public string Attack;
    public string Power;
    [Title("特有属性")]
    public float moveSpeed;

15.TypeFilter

According to my understanding, it is to display subclasses through the base class. I have never used it before.

Official example code provided

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

animated cover

16.TypeInfoBox

It is another prompt message box, but it can be marked on the class instead of having to be marked on the variable.

    [HideLabel]
    public Student st;
    [Serializable,TypeInfoBox("学生基本信息")]
    public class Student
    {
    
    
        public string Name;
        public int Score;
    }

17.ValidateInput

Input validation can verify the value you enter and give feedback

    [ValidateInput("CheckPlayerAge","",InfoMessageType.Error)]
    public int playerAge;

    public bool CheckPlayerAge(int age,ref string errorMessage,ref InfoMessageType? messageType)
    {
    
    
        errorMessage = "角色未成年";
        return age >= 18;
    }

animated cover

18.ValueDropDown

Drop-down list, like the display form of enumeration type, where arrays or other values ​​with enumerators can be displayed in this way.

    [ValueDropdown("PlayerLevel")]
    public int playerLevel;
    public static List<int> PlayerLevel = new List<int>() {
    
    1,2,3,4 };

The above are some of the basic nodes of Odin. Students with plug-ins can also import them into Unity and then use

Tools–>OdinInspector–>Attribute OverviewView


the second part

1.Button

It can be said to be the most commonly used feature, bar none! ! , mark it on the method to quickly implement click execution.

    public int value;
    [Button("改变值",ButtonSizes.Large)]
    public void ShowName()
    {
    
    
        value++;
    }

animated cover

2.ButtonGroup

A group of horizontally arranged buttons can also be implemented using HorizontalGroup (will be introduced later)

    [Button("Show1"), ButtonGroup]
    public void ShowValue1() {
    
     }
    [Button("Show2"), ButtonGroup]
    public void ShowValue2() {
    
     }
    [Button("Show3"), ButtonGroup]
    public void ShowValue3() {
    
     }

3.EnumPaging

Display enumerated types in pagination, not used much

    [EnumPaging]
    public SubjectType st;
    public enum SubjectType {
    
    English,Math,Arts}

animated cover

4.EnumToggleButton

Display the enumeration value as a row of buttons,

    [EnumToggleButtons]
    public SubjectType st;
    public enum SubjectType {
    
    English,Math,Arts}

animated cover

5.InlineButton

Display the button after the variable. This is more commonly used by me. I usually use it to make reset buttons and load buttons.

    [InlineButton("Reset")]
    public StudentScore ss;
    public void Reset()
    {
    
    
        ss = new StudentScore();
    }
    [Serializable]
    public class StudentScore
    {
    
    
        public float math = 100;
        public float english = 50;
        public float arts = 100;
    }

animated cover

6.ResponsiveButtonGroup

Automatically adapt the position and size of the button according to the layout space. It is not commonly used. The approximate effect is like this.

animated cover

7.DictionaryDrawerSettings

Displaying the dictionary on the Inspector is quite special. It requires the serialization function of Odin, and the script where the dictionary is located must inherit the SerializedMonoBehaviour serialized by Odin .

public class OdinTest : SerializedMonoBehaviour
{
    
    
    [DictionaryDrawerSettings]
    public Dictionary<string, float> StudentDict = new Dictionary<string, float>();
}

Then after Unity is compiled, the following prompt message will appear. Click to hide it.

animated cover

When adding values ​​to the dictionary, there is also a display that duplicate keys cannot be added, which is very user-friendly.

8.ListDrawerSettings

The rendering of the list is okay.

In addition, after Odin is imported into Unity, the default array or List can be dragged to change the order of elements. This function is very useful, and you can also turn off the dragging function manually.

    [ListDrawerSettings(ShowIndexLabels =true)]
    public List<Student> studentList = new List<Student>();
    [ListDrawerSettings(ShowIndexLabels = true,DraggableItems =false)]
    public List<Student> studentList1 = new List<Student>();
    [Serializable]
    public class Student
    {
    
    
        public string name;
        public int Id;
        public float score;
    }

animated cover

9. TableList

Display the List in the form of a table. The header is the attribute name. You can also manually switch the display mode. It’s easy to use! !

    [TableList]
    public List<Student> studentList = new List<Student>();
    [TableList,TableColumnWidth(20,Resizable =false)]
    [Serializable]
    public class Student
    {
    
    
        public string name;
        public int Id;
        public float score;
    }

animated cover

10.TableColumnWidth

Set the column width of the table and limit the drag width, use it together with the above

    [TableList]
    public List<Student> studentList = new List<Student>();
    [Serializable]
    public class Student
    {
    
    
        [TableColumnWidth(50,Resizable =false)]
        public string name;
        public int Id;
        public float score;
    }

animated cover

11.TableMatrix

Another feature that requires the use of Odin's own serialization tool. The script class also needs to inherit SerializedMonoBehaviour, which can convert a two-dimensional array into a table display form.

    [TableMatrix(SquareCells = false)]
    public int[,] MapData = {
    
    
        {
    
     1,1,1,0} ,
        {
    
     1,1,0,1},
        {
    
     1,0,1,1},
        {
    
     0,1,1,1}
    };

animated cover


the third part

The book continues from the previous chapter and continues the introduction of Odin’s features.

1. Basic condition characteristics

1.DisableIf, EnableIf, HideIf, ShowIf

It is easy to see from the names, they are freeze, activate, hide and show.

When using it, just follow the condition. The condition can be a Bool type variable, an enumeration type variable, an expression that returns a Bool value, or a method name that returns a Bool value.

First is the Bool variable

    public bool AAA;
    [DisableIf("AAA")]
    public string DisableWhenA;
    [EnableIf("AAA")]
    public string EnableWhenA;
    [HideIf("AAA")]
    public string HideWhenA;
    [ShowIf("AAA")]
    public string ShowWhenA;

animated cover

Briefly describe

When AAA is True,

DisableWhenA detects condition passing and is frozen

EnableWhenA detects that a condition is activated by

HideWhenA detects that the condition is hidden by

ShowWhen the detection condition is displayed through

When AAA is False,

DisableWhenA detection condition is not passed and is activated

EnableWhenA detection condition fails and is frozen

HideWhenA detection condition fails and is displayed

ShowWhen the detection condition fails and is not displayed

Next is the enumeration type. This is relatively simple. If the enumeration values ​​are the same, the test passes.

    public enum SubjectType {
    
     Math,English,Arts}
    public SubjectType sType;

    [ShowIf("sType", SubjectType.Math)]
    public int mathScore;
    [ShowIf("sType", SubjectType.English)]
    public int EnglishScore;
    [ShowIf("sType", SubjectType.Arts)]
    public int ArtsScore;

animated cover

Expressions and methods will be introduced together.

    [EnableIf("@1==2")]
    public string Show1;

    [EnableIf("Show2Method")]
    public string Show2;

    private bool Show2Method()
    {
    
    
        return false;
    }

2. Advanced conditional characteristics

These conditions are related to the state of the object in UnityEditor

Odin divides objects in UnityEditor into several states, namely

Editor Mode – the non-running state of the Unity editor

Inline Editors–Object preview status (this may not be easy to understand, just look down)

NonPrefabs – not from prefabs

PlayMode–Unity’s running status

PrefabAssets – prefab resources, resources

Prefab Instances – Prefab instances, scenes

Prefabs – prefabs, scenes and assets

1.DisableInEditorMode,HideInEditorMode

Freeze or hide in non-running state, and can be modified after the editor is run.

Properties are frozen by default

is activated after running

2.DisableInInlineEditors,ShowInInlineEditors

This needs to be explained first. InlineEditor can display detailed information of classes that inherit UnityEngine.Object, such as the more common ScriptableObject.

[CreateAssetMenu(menuName = "InLineTest")]
public class InLineTest : ScriptableObject
{
    
    
    public string myName;
    public int myAge;
}

//在我们之前的OdinTest脚本中引用
    [InlineEditor(InlineEditorModes.FullEditor)]
    public InLineTest mt;

It will be the following effect

You can see that this ScriptableObject is displayed in the Inspector, and the properties are all activated.

[CreateAssetMenu(menuName = "InLineTest")]
public class InLineTest : ScriptableObject
{
    
    
    public string myName;
    [DisableInInlineEditors]
    public int myAge;
}

When we mark one of the properties, it will be frozen in preview mode

3.DisableInNonPrefabs,HideInNonPrefabs

If the object in the scene does not come from a prefab, it will be frozen or hidden. Clicking to open the prefab will enter a new scene. The prefab here is equivalent to an ordinary object, so the variables at this time will be frozen or hidden.

The objects in the scene come from prefabs, so they will not be frozen.

In prefab editing mode, it is equivalent to an ordinary object without a source and will be frozen.

4.DisableInPlayMode,HideInPlayMode

Contrary to the first point above, frozen or hidden in running state, activated by default

5.DisableInPrefabAssets,HideInPrefabAssets

Frozen or hidden when opened as a prefab resource, activated after dragging the prefab into the scene

Properties on ordinary objects in the scene without prefab sources are also active.

6.DisableInPrefabInstances,HideInPrefabInstances

When a prefab instance exists in the scene, it is frozen or hidden. When the prefab is in the active state, it can be displayed and modified.

7.DisableInPrefabs,HideInPrefabs

Prefab properties in the scene are frozen or hidden

To summarize, the above things look a bit confusing, including display and hiding in various modes, activation and freezing, but they are rarely used in actual development. Anyway, I have never used them. I think it is enough to master the basic condition judgments. , these advanced understanding functions are enough.


3. Grouping

1.BoxGroup

Putting fields in the same group into a box is very useful to separate categories.

    [BoxGroup("BaseInfo",CenterLabel=true)]
    public string studentName;
    [BoxGroup("BaseInfo", CenterLabel = true)]
    public string studentAge;
    [BoxGroup("BaseInfo", CenterLabel = true)]
    public string studentSex;

    [BoxGroup("Score", CenterLabel = true)]
    public string EnglishScore;
    [BoxGroup("Score", CenterLabel = true)]
    public string MathScore;
    [BoxGroup("Score", CenterLabel = true)]
    public string ArtScore;

2.FoldoutGroup

The only difference from the above is that it can be folded, which is very convenient to use when there are many variables. I like this better.

    [FoldoutGroup("BaseInfo")]
    public string studentName;
    [FoldoutGroup("BaseInfo")]
    public string studentAge;
    [FoldoutGroup("BaseInfo")]
    public string studentSex;

    [FoldoutGroup("Score")]
    public string EnglishScore;
    [FoldoutGroup("Score")]
    public string MathScore;
    [FoldoutGroup("Score")]
    public string ArtScore;

animated cover

3.HorizontalGroup,VerticalGroup

Horizontal and vertical layout. Horizontal layout is useful. Unity is originally vertical, so there is no need to use this vertical layout.

    [HorizontalGroup("BaseInfo"),HideLabel]
    public string studentName;
    [HorizontalGroup("BaseInfo"), HideLabel]
    public string studentAge;
    [HorizontalGroup("BaseInfo"), HideLabel]
    public string studentSex;

    [VerticalGroup("Score")]
    public string EnglishScore;
    [VerticalGroup("Score")]
    public string MathScore;
    [VerticalGroup("Score")]
    public string ArtScore;

Here I hide the labels of the variables in the horizontal layout, which looks more convenient.

4.TabGroup

This is a bit interesting, tab layout

    [TabGroup("BaseInfo")]
    public string studentName;
    [TabGroup("BaseInfo")]
    public string studentAge;
    [TabGroup("BaseInfo")]
    public string studentSex;

    [TabGroup("Score")]
    public string EnglishScore;
    [TabGroup("Score")]
    public string MathScore;
    [TabGroup("Score")]
    public string ArtScore;

animated cover

5.TitleGroup

Titled grouping is similar to box grouping

    [TitleGroup("BaseInfo")]
    public string studentName;
    [TitleGroup("BaseInfo")]
    public string studentAge;
    [TitleGroup("BaseInfo")]
    public string studentSex;

    [TitleGroup("Score")]
    public string EnglishScore;
    [TitleGroup("Score")]
    public string MathScore;
    [TitleGroup("Score")]
    public string ArtScore;

6.ToggleGroup

emmm, grouping with switches needs to be used with a bool value variable that is the same as the group name. It has not been used officially.

    [ToggleGroup("BaseInfo")]
    public bool BaseInfo;
    [ToggleGroup("BaseInfo")]
    public string studentName;
    [ToggleGroup("BaseInfo")]
    public string studentAge;
    [ToggleGroup("BaseInfo")]
    public string studentSex;

    [ToggleGroup("Score")]
    public bool Score;
    [ToggleGroup("Score")]
    public string EnglishScore;
    [ToggleGroup("Score")]
    public string MathScore;
    [ToggleGroup("Score")]
    public string ArtScore;


fourth part

The book continues from the previous chapter and continues the introduction of Odin’s features.

1.MaxValue

Limit the maximum value of a field or attribute

    [MaxValue(18)]
    public int grilAge;

animated cover

2.MinMaxSlider

The minimum and maximum slide bars are used to describe variables of type V2. xy is the minimum and maximum values ​​respectively.

    [MinMaxSlider(0, 18)]
    public Vector2Int grilAgeRange;

3.MinValue

Limit the minimum value of a field or attribute

    [MinValue(0)]
    public float studentScore;

animated cover

4.ProgressBar

Display the variables in the form of a progress bar, similar to Range, which is also a maximum and minimum value limit, but this may look better?

    [ProgressBar(0,1)]
    public float Progress;

animated cover

5.PropertyRange

Property range display is the same as Unity's Range, except that this is for properties and needs to be displayed with ShowInInspector.

    [ShowInInspector,PropertyRange(0,1)]
    public float Progress {
    
     get; set; }

6.Wrap

Values ​​cycle through the specified range

    [Wrap(0,10)]
    public int Score;

animated cover

Numbers cycle between 0-9

7.AssetList

Resource list, after marking the attributes, click the button in the upper right corner to quickly select and switch resources of the same type.

    [AssetList]
    public Material mat;

8.AssetSelector

The resource selector is similar to the one above. This click will also bring up a selection menu, but this time you click the three dots in front of it.

    [AssetSelector]
    public Material mat;

9.ChildGameObjetsOnly

Limit selection of sub-objects

    [ChildGameObjectsOnly]
    public GameObject child;

10.ColorPalette

Palette, well, it should be very convenient for color matching. You can select colors directly from the presets.

    [ColorPalette]
    public Color color;

animated cover

11.DisplayAsString

Display the field value as a read-only string

    [DisplayAsString]
    public Color col;

12.FilePath

File path is used to modify strings. I prefer to use it to store addresses. It is also very convenient to use. Just drag and drop.

    [FilePath]
    public string gameObjectPath;

animated cover

13.FolderPath

Folder path, usage is the same as the above file, except this is dragging the folder

    [FolderPath]
    public string gameObjectFolderPath;

animated cover

Note that when dragging an object onto it, the path to the folder where the object is located will be added.

14.HideInTables

Hide in the table. This is related to the TableList introduced before. As mentioned before, TableList displays the List in the form of a table. HideInTables means that the marked attributes are not displayed in the table.

    [TableList]
    public List<Student1> st1;
    [TableList]
    public List<Student2> st2;
    [Serializable]
    public class Student1
    {
    
    
        public string Id;
        public string Name;
        public string Age;
    }
    [Serializable]
    public class Student2
    {
    
    
        [HideInTables]
        public string Id;
        public string Name;
        public string Age;
    }

15.HideMonoScript

Hide Mono script

[HideMonoScript]
public class OdinTest : MonoBehaviour
{
    
    
    public string Show="SSSSS";
    public string Hide="HHHHH";
}

before hiding

After hiding

16.Hide Network Behaviour Fields

UNet has been deprecated, so this is no longer useful.

The official description reads like this

HideNetworkBehaviour marks your class to prevent the special "NetWork Channel" and "NetWorkSendInterval" properties from being displayed as a NewWorkBehaviour in the Inspector. This property has no effect on classes that do not inherit NetworkBehaviour.

No examples are given, and even if they are given, they won’t be used.

17.Hide Reference Object Picker

This is not easy to explain. I have never used it before. Just look at the picture.

    public MyV3 Show;
    [HideReferenceObjectPicker]
    public MyV3 Hide;

    public class MyV3
    {
    
    
        public float x, y, z;
    }

The following features are added to hide this thing.

18.Inline Editor

This was introduced before when I introduced HideInInlineEditor. You can take a look at the previous article.

The second part of the advanced conditional features is introduced.

19.MultiLineProperty

Used to modify strings and display multi-line text. It has the same function as TextArea in Unity. I am more accustomed to using the latter.

    [MultiLineProperty]
    public string MultTex;

20.Preview Field

Preview the selected object. I am more used to previewing pictures, and the effect is good.

    public Sprite lsp;
    [PreviewField]
    public Sprite sp;

The ones above are normal and cannot be previewed, while the ones below can be seen as thumbnails.

21.Toggle

Switches can be used on any field or property to activate or freeze its behavior on the Inspector.

Note that the class must contain a Bool variable with the same name as the string parameter in the attribute.

    public MyToggle t1, t2;
    [Serializable,Toggle("Enable")]
    public class MyToggle
    {
    
    
        public bool Enable;
        public string Name;
        public string Age;
    }

22.ToggleLeft

Place the check box of the Bool value type to the left of the Label to display it, which looks much more comfortable.

    [ToggleLeft]
    public bool Left;
    public bool Normal;


Odin has a lot of features, no wonder the plug-ins are a bit expensive


the fifth part

1.CustomContextMenu

Customized right-click menu

    [CustomContextMenu("SetAgeTen", "SetValueAsTen")]
    public int Age;
    public void SetValueAsTen()
    {
    
    
        Age = 10;
    }

animated cover

2.DisableContextMenu

Disable right-click menu

    [DisableContextMenu]
    public int DisableAge;

Right-click on Properties and there will be no menu.

3.DrawWithUnity

Use Unity's default display method to display the properties on the Inspector. After Odin is imported into Unity, Odin will change the display mode of the properties. This property is equivalent to resetting the properties back.

    public GameObject DrawInOdin;
    [DrawWithUnity]
    public GameObject DrawInUnity;

The above is the display method of Odin, and the following is the default display method of Unity.

4.HideDuplicateReferenceBox

The official description states that Odin should hide references, otherwise the property will be drawn as a reference to another property due to encountering a duplicate referenced value. Note that if the value is a recursive reference itself, the reference box will be drawn regardless of whether this attribute is present in all recursive rendering callbacks.

Then they gave an example of recursion, but I couldn't understand how to use it. . . I think he just doesn't want to teach me

After an hour of trying, I finally found some differences.

First I created two new scripts

public class OdinTest : SerializedMonoBehaviour
{
    
    
    [HideDuplicateReferenceBox]
    public MyV3 mv3;
    [HideDuplicateReferenceBox]
    public MyV3 dmv3;
    public class MyV3
    {
    
    
        public string name;
    }
}

This script declares two variables of the same type

public class OdinTest1 : MonoBehaviour
{
    public OdinTest ot1;
    public OdinTest ot2;
    [Button]
    private void ReadValue()
    {
        ot2.mv3 = ot1.mv3;
        ot2.dmv3 = ot1.mv3;
    }
}

This script is used for assignment. I plan to make two instances of the first script in the scene. This script obtains references from two objects and assigns the first value in the first one to the second one. The two values ​​​​in it

The above is what the test scenario looks like. After hanging the script, click the button to assign the value.

This is what the values ​​​​of the two variables look like without describing the characteristics. You can see that the two variables above have the same source. The second variable has the same value as the first variable and comes from the same object. So it is framed inside a Box.

This is what it looks like after adding variables, which is equivalent to hiding the Box, but the values ​​will still be synchronized.

I don’t know what this feature can be used for, it seems useless.

5.Indent

Indent, used to control the indentation of attribute tags

    [Indent] public int A;
    [Indent(2)] public int B;
    [Indent(-2)] public int C;

6.InfoBox

Information box, used to describe properties in detail

    [InfoBox("abcdefg\nhijklmn\nopqrst")]
    public int MyMathScore;

7.InlineProerty

Display serialized attributes and labels on the same line

    [InlineProperty]
    public MyV3 mvInLine;
    public MyV3 mv;
    [Serializable]
    public class MyV3
    {
    
    
        [HorizontalGroup(LabelWidth =10)]
        public int x, y, z;
    }

As you can see from the picture above, the above attributes are displayed on the same line, and the following ones need to be clicked to expand.

8.LabelText

I especially like to change the label text and simply describe the variable.

    [LabelText("我的成绩")]
    public float myScore;

9.LabelWidth

Limit label length

    [LabelText("我的成绩"),LabelWidth(20)]
    public float myScore;

10.OnCollectionChanged

Triggered when the collection changes. It is used to monitor changes in the collection. I often use it on List.

    public int count = 0;
    [OnCollectionChanged("ShowListCount")]
    public List<string> nameList;

    private void ShowListCount()
    {
    
    
        count = nameList.Count;
    }

animated cover

11.OnInspectorDispose

InspectorDispose fires when rearranged

    [OnInspectorDispose("ChangeCount")]
    public int count = 0;

    private void ChangeCount()
    {
    
    
        count++;
    }

animated cover

12.OnInspectorGUI

Similar to Unity's OnGUI or Update logic, it is equivalent to the Inspector's OnGUI, which is always executed when the current Inspector is displayed.

    [OnInspectorGUI("ChangeCount")]
    public int count = 0;

    private void ChangeCount()
    {
    
    
        count++;
    }

animated cover

13.OnInspectorInit

Triggered when the Inspector is initialized, equivalent to Start or Awake

    [OnInspectorInit("ChangeCount")]
    public int count = 0;

    private void ChangeCount()
    {
        count++;
    }

animated cover

Every time an object is copied, the script on the object will execute Init once, triggering the self-increment operation, so the above effect will appear.

14.OnStateUpdate

Executed once per frame,

    [OnStateUpdate("ChangeCount")]
    public bool OnStateChange;
    public int count = 0;
    private void ChangeCount()
    {
    
    
        if(OnStateChange)
        count++;
    }

animated cover

15.OnValueChanged

Triggered when the value changes, more commonly used

    [OnValueChanged("ChangeCount")]
    public bool OnStateChange;
    public int count = 0;
    private void ChangeCount()
    {
    
    
        count++;
    }

animated cover

16.PropertyToolTip

Prompt when the mouse is hovering over the attribute

    [PropertyTooltip("我的成绩")]
    public float myScore;

animated cover

17.SuffixLabel

Suffix label, the label is displayed after the attribute

    [SuffixLabel("我的成绩",Overlay =true)]
    public float myScore;

18.SuppressInvaildError

Turn off error reporting for unavailable features

    [Range(0, 10), SuppressInvalidAttributeError]
    public string myScore1;

    [Range(0, 10)]
    public string myScore2;

19.ShowDrawerChain

Display drawing connection is another unused thing

Official description, ShowDrawerList lists all prefixed, appended and value Drawers used in the Inspector. Very useful when you want to debug and want to know which Drawers may be involved in drawing properties.

In human terms, it means displaying all Drawers (I think it can be understood as the meaning of drawers)

    [Range(0, 10)]
    [ShowDrawerChain]
    public float SomeRange;

The above is the result of using the current attribute painter

Then I added an InfoBox to the property

    [Range(0, 10)]
    [ShowDrawerChain]
    [InfoBox("SSSSSSSome")]
    public float SomeRange;

It can be seen that there is an additional InfoBox painter

20.ShowPropertyResolver

Show attribute parser

    public MyV3 myV3;
    [ShowPropertyResolver]
    public MyV3 myV32;
    [Serializable]
    public class MyV3
    {
    
    
        public float x, y, z;
    }

After adding the tag, there will be an additional thing like this, which can display the type of the attribute. I feel it is useless.


At this point, all the characteristics of Odin have been introduced, and the flowers are finished. .

Guess you like

Origin blog.csdn.net/m0_58523831/article/details/132433504