| Syntax | [Name], [Name(args)] |
|---|---|
| Category | Metadata / reflection |
| In Unity | [SerializeField], [Header], [Range], [RequireComponent], [CreateAssetMenu] |
Attributes
Attributes are labels in square brackets that you attach to classes, fields or methods. They don't change what your code does by themselves. Instead, other code (Unity's Editor, the compiler, or your own tools) reads them and acts on them.
Sticky notes on a filing cabinet. "FRAGILE" on a box doesn't make it fragile; it tells the movers how to handle it. [Range(0, 10)] doesn't limit your field in code; it tells the Inspector to draw a slider from 0 to 10.
Unity Inspector attributes
| Attribute | Goes on | Effect |
|---|---|---|
[SerializeField] | Private field | Show and save it in the Inspector |
[HideInInspector] | Public field | Still saved, but hidden from the Inspector |
[System.NonSerialized] | Public field | Not saved and not shown |
[Header("Movement")] | Field | Bold heading above it |
[Tooltip("...")] | Field | Hover text |
[Range(0f, 1f)] | float/int field | Slider |
[Min(0)] | float/int field | Can't go below the value in the Inspector |
[Space(10)] | Field | Empty gap |
[TextArea(3, 10)] | string field | Multi-line text box |
[ColorUsage(true, true)] | Color field | Color picker with alpha/HDR |
[System.Serializable] | Your own class/struct | Lets Unity show fields of that type |
Unity class and method attributes
| Attribute | Effect |
|---|---|
[RequireComponent(typeof(Rigidbody))] | Adds the component automatically and prevents removing it |
[DisallowMultipleComponent] | Only one of this script per GameObject |
[CreateAssetMenu(menuName = "...")] | Adds a ScriptableObject to the Create menu |
[AddComponentMenu("Game/Health")] | Where it appears in the Add Component menu |
[ExecuteAlways] | Runs Update etc. in Edit Mode too (careful!) |
[ContextMenu("Reset Stats")] | On a method: adds it to the component's ⋮ menu, so you can run it from the Inspector |
[SelectionBase] | Clicking a child in the Scene view selects this object instead |
Example: a well-labeled component
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
[DisallowMultipleComponent]
[AddComponentMenu("Game/Enemy Stats")]
public class EnemyStats : MonoBehaviour
{
[Header("Health")]
[Tooltip("Health when spawned.")]
[SerializeField, Min(1)] private int maxHealth = 50;
[Header("Movement")]
[SerializeField, Range(0f, 20f)] private float speed = 4f;
[Space]
[SerializeField, TextArea(2, 5)] private string designerNotes;
[ContextMenu("Double Health")]
private void DoubleHealth()
{
maxHealth *= 2;
}
}
Several attributes can go in one set of brackets, separated by commas: [SerializeField, Range(0, 1)].
C# attributes you'll meet
| Attribute | Effect |
|---|---|
[System.Obsolete("Use X instead")] | Warns anyone who uses this method. How Unity marks old APIs like FindObjectOfType. |
[System.Flags] | An enum whose values combine. See Enums. |
[System.Diagnostics.Conditional("UNITY_EDITOR")] | Calls to this method are removed unless the symbol is defined. |
Making your own attribute
Create a class that inherits from System.Attribute. Then read it with reflection using GetType().
using System;
using System.Reflection;
using UnityEngine;
// The attribute: its name must end in "Attribute"; you use it without that part
[AttributeUsage(AttributeTargets.Method)]
public class CheatAttribute : Attribute
{
public string Command { get; }
public CheatAttribute(string command) { Command = command; }
}
public class Player : MonoBehaviour
{
[Cheat("god")] public void GodMode() { Debug.Log("God mode on"); }
[Cheat("heal")] public void FullHeal() { Debug.Log("Healed"); }
}
// A debug console that finds cheat methods automatically
public class CheatConsole : MonoBehaviour
{
[SerializeField] private Player player;
public void Run(string command)
{
foreach (MethodInfo method in player.GetType().GetMethods())
{
var cheat = method.GetCustomAttribute<CheatAttribute>();
if (cheat != null && cheat.Command == command)
{
method.Invoke(player, null);
return;
}
}
Debug.LogWarning($"Unknown cheat: {command}");
}
}
What happens at runtime
- The compiler stores attributes as extra data (metadata) next to your compiled code.
- Unity's Editor reads Inspector attributes when drawing components. They have no effect on your game's logic or performance.
- Reading attributes yourself uses reflection, which is slow. Do it once (e.g. at startup) and cache the results, not every frame.
Common Mistakes
- Expecting
[Range]to clamp in code. It only limits the Inspector slider.speed = 999in code still works. Clamp in code if it matters. - Adding
[RequireComponent]to a script already on objects. It only auto-adds when the script is added. Existing objects aren't updated. [SerializeField]on a property. Doesn't work. Use[field: SerializeField]on an auto-property.- Custom classes not showing in the Inspector. Add
[System.Serializable]to the class.
See also
- Fields, Properties & Modifiers
- Types & Type Checking (GetType and reflection)
This page is a simplified, AI-assisted interpretation. For the complete and authoritative reference, see the official Microsoft C# documentation.