Repository navigation
Property Drawers
A property drawer replaces the field control. Unity allows one drawer per field. A second drawer attribute on that same field is ignored, so DropdownList, LayerSelector and LimitedField cannot share a field.
Decorators still work on that field. They draw around the drawer instead of competing with it:
[InfoBox("Ground checks use this layer.", InfoBoxType.Info)]
[AvailableIf(nameof(_useCustomLayer))]
[LayerSelector]
[SerializeField] private int groundLayer;The attributes below are in Mane.Unity. Type drawers, which do not use an attribute of your own, are linked at the bottom.
Draws a string (stored text) or an int (stored index) as a popup. Anything else shows a warning instead of a dropdown.
Fixed list, or a parameterless method or property returning string[] (public or private, static or instance, including base types). An empty result falls back to the normal field. A stored value that is not one of the options (unset, removed, or an out-of-range index) shows as empty until you pick one. Dynamic options can be refreshed from the field context menu (Refresh Options).
[DropdownList(typeof(LevelCatalog), nameof(LevelCatalog.GetIds))]
[SerializeField] private int levelId;
[DropdownList("Easy", "Normal", "Hard")]
[SerializeField] private string difficulty;
Rename elements of a collection in the inspector. Put the attribute on the collection.
ItemNameFromField reads a nested serialized field. Optional prefix and postfix wrap that value.
[ItemNameFromField(nameof(Wave.name))]
[SerializeField] private Wave[] waves;
[ItemNameFromField(nameof(Slot.id), prefix: "#")]
[SerializeField] private Slot[] slots;
If you do not want to expose the field as public for this, point the attribute at a const:
[ItemNameFromField(Wave.PropertyName)]
[SerializeField] private Wave[] waves;
[Serializable]
public class Wave
{
[SerializeField] private int id;
[SerializeField] private string name;
public const string PropertyName = nameof(id);
}ItemNameFromString formats {0} as the element index. startingIndex is the number used for the first element (default 0). A label without {0} keeps the normal element name and shows a warning on the first element.
[ItemNameFromString("Slot {0}", startingIndex: 1)]
[SerializeField] private int[] slots;
Draws an int field as a Unity layer dropdown. Other types show a warning.
[SerializeField, LayerSelector] private int groundLayer;
Draws a plain int or float field with LimitedIntField / LimitedFloatField. Other types, including double and long, show a warning.
Negative values are clamped to 0. With allowNegatives the only negative value is -1 (anything below becomes -1). The first argument is the text shown instead of 0, and negativeLabel is the text shown instead of -1 (it needs allowNegatives). An empty text shows the number. You can type the label text into the field to set that value.
On a collection it applies to every element. It combines with Label and Prefix / Postfix.
[SerializeField, LimitedField("Unlimited")]
private int maxCount; // only positives (zero as special state)
[SerializeField, LimitedField(allowNegatives: true, negativeLabel: "Default")]
private int count; // only positives, zero included (-1 as a special state)
[SerializeField, LimitedField("Instant", allowNegatives: true, negativeLabel: "Default")]
private float delay = -1f; // -1 and zero as 2 different separate special statesThese replace the field too, so the one-drawer rule applies. Each has its own page:
-
Interface Serialization —
SerializeInterface(managed reference) andInterfaceOnly(object reference) -
Serializable DateTime —
SerializableDateTimeandSerializableDateTimeRange, with the calendar popup -
MinMax —
MinMaxInt,MinMaxFloat,MinMaxDoubleas one min/max row. The drawer swaps the endpoints if you invert them. -
ParticleSystem.MinMaxCurve– customManeStyledrawer, used in Particle System UI Scaler -
Easing —
EasingCurveon anAnimationCurve: a dropdown of the easing presets, with the curve field forCustom
openupm add com.manefunction.tools-unity