How To Use
Prerequisites: Familiarity with basic C# programming in Unity and knowledge about how to use Unity’s built-in attributes.

Importing The Namespace
To start using the editor attributes you must add this using statement in your class:
using EditorAttributes;

If you are using Assembly Definitions in your project make sure you reference the “EditorAttributes” Assembly Definition where needed.

Serialization
Every member the attribute is attached to must be serializable by Unity (with the exception of the Button Attribute and ShowInInspector Attribute), meaning those members must be either public or private with the SerializeField Attribute and valid to the Unity serializer.
Here is a small example of what’s valid and what’s not:
// Valid, public fields are serialized by default
public int field01;

// Valid, is still a public field, we just mark it to be hidden in the inspector
[HideInInspector] public int field02;

// Invalid, private fields are not serialized by default
private int field03;

// Valid, we mark this private field to be serialized by unity
[SerializeField] private int field04;

// Valid, is still serialized, we just hide it in the inspector
[SerializeField, HideInInspector] private int field05;

// Invalid, static, readonly or const fields are not valid to unity's serializer
public static int field06;

// Invalid, Non-Behaivour classes and structs that are not marked as serializable are not serialized by unity
public CustomRawClass field07;

For more details about unity serialization see this

Attribute Order
The logic of all attributes is executed in the order they are written (left to right), meaning the last attribute can override the functionality of the previous attribute if the functionality is similar. In the following example the TimeField Attribute will execute before the Suffix Attribute meaning the suffix will fail to add because of how the TimeField Attribute is drawn:
using UnityEngine;
using EditorAttributes;

public class AttributesExample : MonoBehaviour
{		
        [TimeField(TimeFormat.YearMonthWeek, ConvertTo.Days), Suffix("to days")]
        [SerializeField] private int field;
}

To fix this we can change the order by putting the TimeField Attribute after the Suffix Attribute or use the order parameter that every attribute has to execute the Suffix Attribute first, C# will first go through the attributes with the lowest order from left to right then to the ones with the higher order the same way, the default order of all attributes is 0:

using UnityEngine;
using EditorAttributes;

public class AttributesExample : MonoBehaviour
{
        [TimeField(TimeFormat.YearMonthWeek, ConvertTo.Days), Suffix("to days", order = -1)]
        [SerializeField] private int field;
}

So now the Suffix Attribute will be executed first and the TimeField Attribute will draw the field with the suffix already on it.

Good Practices
Here are a few good practices to follow when using this package.

Note:
These are just some general recommendations to follow when using this package, you don’t have to abide by them like laws, if you already have a workflow that fits better for you, feel free to use it.

Using the void struct
The Void Struct is made to act as a holder for attributes that redraw the property is attached to. While it’s not necessary to use the struct for those attributes (any serialized data type can be used), using the struct as a holder makes the code more readable for you and others.
When you use the Void Struct as a variable it makes it obvious that is a holder and it will be redrawn, it also keeps some consistency in your code rather than using int or float randomly in your code as holders.
Is also a good idea to add a holder suffix or other naming convention to the void fields so when it comes up in something like IntelliSense you know what it is.
Managing multiple attributes
When an attribute has a lot of parameters or you use multiple attributes on one field, that line of code can become pretty long which is generally a bad thing. Here is an example:
using UnityEngine;
using EditorAttributes;

public class AttributesExample : MonoBehaviour
{
        [SerializeField] private bool condition01;
        [SerializeField] private bool condition02;
        [SerializeField] private bool condition03;

        [SerializeField, ReadOnly, ConditionalField(ConditionType.AND, new bool[] { false, true, false }, nameof(condition01), nameof(condition02), nameof(condition03))] private int field;
}
Our int field got pretty long, let’s see what can we do to organize this better.
•	We can put the variable on a separate line with all attributes above it:
[SerializeField, ReadOnly, ConditionalField(ConditionType.AND, new bool[] { false, true, false }, nameof(condition01), nameof(condition02), nameof(condition03))]
private int field;
•	Keep the attributes from the package and the built-in Unity ones separate:
[ReadOnly, ConditionalField(ConditionType.AND, new bool[] { false, true, false }, nameof(condition01), nameof(condition02), nameof(condition03))]
[SerializeField] private int field;
•	Put the attribute with a lot of parameters on a separate line:
[ConditionalField(ConditionType.AND, new bool[] { false, true, false }, nameof(condition01), nameof(condition02), nameof(condition03))]
[SerializeField, ReadOnly] private int field;
Any of these methods are valid ways of shortening the line of code, is up to you which one you prefer.
Using the nameof expression
Some attributes need to look for a member in your script and it will ask you to give the name of that member as a string parameter, but strings are error prone and you might encounter issues saying, that field cannot be found and spend hours scratching you head when you realize you just made a typo or had a character in the wrong case. Thats why you should use the nameof expression, that allows you to add your variable like a parameter and converts its name to a string for the attribute:
using UnityEngine;
using EditorAttributes;

public class AttributesExample : MonoBehaviour
{
        [SerializeField] private bool condition01;

        // Passing the variable as a string (error prone)
        [SerializeField, EnableField("condition01")] private int field01;

        // Using the nameof condition
        [SerializeField, EnableField(nameof(condition01))] private int field02;
}

Note:
The only exception to using the nameof expression is when you need to input the entire path to a member inside another type, for more details see How To Use.
Void Struct
The Void struct is an empty serialized struct to use as a holder property for attributes like the VerticalGroup Attribute, HorizontalGroup Attribute, etc. that completely redraw the property in the inspector.
By itself the Void struct will not be drawn in the inspector but attributes attached to it will still execute.
If you are using the System namespace and EditorAttributes namespace in your script then use the Void struct you will notice a naming conflict between System.Void and EditorAttributes.Void, to fix that you will just have to specify which version you want to use, and there are 2 ways to do that.
1.	Specify the namespace of the version you want to use on that line:
private System.Void systemVoidField;
// Or
private EditorAttributes.Void attributesVoidField;
2.	Specify which version you want to use for the whole script under your other usings:
using Void = System.Void;
// Or
using Void = EditorAttributes.Void;
A common way this conflict can happen is when you use the editor attributes and serialize structs:
using System;
using UnityEngine;
using EditorAttributes;

public class AttributesExample : MonoBehaviour
{
        [Serializable]
        private struct ExampleStruct
        {
                public int data01;
                public int data02;
        }

        [SerializeField] private ExampleStruct exampleStruct;

        [HelpBox("This is a help box")]
        [SerializeField] private Void helpBoxHolder; // This line will throw an error
}

We can fix the error either by adding using Void = EditorAttributes.Void; between the usings and class declaration or by removing the using System; at the top of the file, then to use the Serializable Attribute we just call the namespace directly:
[System.Serializable]
private struct ExampleStruct
{
        public int data01;
        public int data02;
}
Now which version you want to use if up to personal preferece.

Attributes
To see how each attribute works import the package sample or check out the online documentation