User Rating: 5 / 5

Star ActiveStar ActiveStar ActiveStar ActiveStar Active
 

We can use Inspector Attributes to slightly change the look of our script in the inspector. 
They are helpful when you want to define some constraints or organize your code.
However too many attributes also means messy "back end" code in the script, thus Custom Editors are
better choice if you need something complex.


In this tutorial we'll talk about the following attributes:

Header - Used to create a label above the field
Range - Used to create slider that ranges from - to
HideInInspector - Hides field in the Inspector even if it is public
ExecuteInEditMode - Executes the script in edit mode as if it were in play  mode
Tooltip - Adds tooltip text when cursor is above the field
Space - Creates space behind this field
Multiline - 
Allows multiline editing of the text field
SerializeField 
- Forces serialization of supported types, even if they are private
Context Menu
- Allows you to create an context menu entry that will call specific method from the script 
RequireComponent
- Adds component of defined type when this script is dragged to the GameObject


How to use attributes:

Using attributes is extremely simple. 
Above the appropriate variable or class, in square brackets, write attribute name and if needed, pass arguments to it.

For example:

[Header("Main settings :")]
public bool AutoReload;

 
Header Attribute

Usage : [Header("{write text here}"] 

We can use Header attribute to create a bold text above the field.
Header attribute is great when we want to logically split variables in sections.

Sample :

using UnityEngine;

public class AttributesSample : MonoBehaviour {

    [Header("Main Settings :")]
    public float CharHP = 100f;
    public float CharSpeed = 20f;

    [Header("Weapon Settings :")]
    public float Damage = 50f;

    public float BulletSpeed = 1f;

    public bool AutoReload = false;
}

 

 

Range Attribute

Usage : [Range({minimum},{maximum}]

We can use Range attribute to create a slider that can go from minimum to maximum value. 
It's quite useful in cases when we know what the range of some property is. It ensures that the user will never go over maximum or bellow minimum value, 
thus creating an exception in our code.

Sample :

using UnityEngine;

public class AttributesSample : MonoBehaviour {

    [Range(0, 100)]
    public int OneHundreed = 0;

    [Range(0,1000)]
    public int OneThousand = 0;
}



 

HideInInspector Attribute

Usage : Place above the variable

HideInInspector allows us to hide any variable in the code. In C#, by default, public variables will always be visible in the Inspector.
Sometimes we might not want to expose them, despite of them being public. 

Sample :

public class AttributesSample : MonoBehaviour {

    public string VisibleVar = "";
    [HideInInspector]
    public string InvisibleVar = "";
}

 

ExecuteInEditMode Attribute

Usage : Place above the class that inherits from MonoBehavior

By Default, the code that you write in your scripts gets executed only in Play mode. 
To create scripts that can work in Edit mode as well, we have to use ExecuteInEditMode attribute.
Unlike all the Attributes so far, we place this attribute above the class definition. 


using UnityEngine;

[ExecuteInEditMode]
public class AttributesSample : MonoBehaviour {


    void Update()
    {
        Debug.Log("Hey, I'm working from EditMode!");
    }
}


Be super careful though, modifications in Edit mode can be permanent and if you are not careful you could permanently lose important data. 

 

Tooltip Attribute

Usage: [Tooltip({text here})]

Whether you have a variable with an unclear name or you just want to help Artist understand what some variable does, you will use Tooltip Attribute. 
It will show a small Tooltip in the Inspector when you place cursor above the field which belongs to the affected variable.

Sample :

using UnityEngine;

public class AttributesSample : MonoBehaviour {

    [Tooltip("Serialized JSON/XML/Binary data source")]
    public TextAsset DBSource;
}

 

Space Attribute

Usage: [Space({optional : spacing in pixels})]

Space attribute allows us to create ... well... space between two variables.

Sample :

  public int foo;
    public int foo2;
    [Space()]
    public int foo3;
    [Space(25)]
    public int foo4;

 

 Multiline Attribute

 Usage: [Multiline({optional : number of lines})]

Using the Multiline Attribute, we can define exactly how tall the text field should be in the Inspector, or we can decide not to, in which case it will be expanded to the default value of 3. 
By default, string variables aren't set to multiline in the Inspector. 

 Sample :

using UnityEngine;

public class AttributesSample : MonoBehaviour {

    public string SomeDefaultText;
    [Multiline()]
    public string SomeShorterText;
    [Multiline(5)]
    public string SomeLongText;
}

 

 

SerializeField Attribute

Usage: Place above the appropriate variable

This attribute will force Unity to serialize supported type, even if it's private. However, it does not support properties and static fields.
By default, private variables will not be serialized by Unity, and therefore not visible in the Inspector in C#. If you declare a variable without a modifier, it will be considered private. 

Sample :

using UnityEngine;

public class AttributesSample : MonoBehaviour {

    private string Foo;
    [SerializeField()]
    private string SerializedFoo;
}

 

ContextMenu Attribute

Usage : Above Method [ContextMenu("{name here}")]

ContextMenu Attribute is placed above a function in te script. Once you right click on the Script in the Inspector, created entry will be visible.
Clicking on the entry will call the method above which was the Attribute placed. This is quite convenient since we can also directly modify the values of the Script. 

Sample :

using UnityEngine;

 
public class AttributesSample : MonoBehaviour {

    public int Five;

    [ContextMenu("Log Debug Message")]
    public void WriteMsg()
    {
        Debug.Log("Greetings DigitalHamster user! I was called from a Context Menu entry on this Script!");
        Five = 5;
    }
}

 

RequireComponent Attribute

Usage : Place above the class that inherits MonoBehavior : [RequireComponent(typeof<{write type here}>)]

RequireComponent Is great in cases when we know that our script relies on some component, but we're not sure if the component will be there.
By using the attribute, we ensure that the component will be there because Unity will automatically create the component when the user adds the script to the GameObject.
The User will not be able to remove the required component as long as the script that requires it is attached to the GameObject.



Sample :

using UnityEngine;

[RequireComponent(typeof(Rigidbody))]
public class AttributesSample : MonoBehaviour {

    private void Start()
    {
        GetComponent<Rigidbody>().useGravity = true;
    }
}

 

Conclusion

And there you have it! Now you know about all the cool types of Attributes. Will you be using them? That is up to you.
While they are great for many things, they can also make otherwise readable code unreadable. Especially when used in combination with other attributes. 


Regardless, here's the complete script with every sample used in this Guide.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[ExecuteInEditMode]
[RequireComponent(typeof(Rigidbody))]
public class AttributesSample : MonoBehaviour
{

    public int Five;

    void Update()
    {
        Debug.Log("Hey, I'm working from EditMode!");
    }
    [Header("Main Settings :")]
    public float CharHP = 100f;
    public float CharSpeed = 20f;

    [Header("Weapon Settings :")]
    public float Damage = 50f;

    public float BulletSpeed = 1f;

    public bool AutoReload = false;

    [Range(0, 100)]
    public int OneHundreed = 0;

    [Range(0, 1000)]
    public int OneThousand = 0;

    public string VisibleVar = "";
    [HideInInspector]
    public string InvisibleVar = "";

    [Tooltip("Serialized JSON/XML/Binary data source")]
    public TextAsset DBSource;

    public int foo;
    public int foo2;
    [Space()]
    public int foo3;
    [Space(25)]
    public int foo4;
    public string SomeDefaultText;
    [Multiline()]
    public string SomeShorterText;
    [Multiline(5)]
    public string SomeLongText;

    private string Foo;
    [SerializeField()]
    private string SerializedFoo;

    [ContextMenu("Log Debug Message")]
    public void WriteMsg()
    {
        Debug.Log("Greetings DigitalHamster user! I was called from a Context Menu entry on this Script!");
        Five = 5;
    }

    private void Start()
    {
        GetComponent<Rigidbody>().useGravity = true;
    }
}

 

Hopefully, you found this tutorial helpful and informative!

Srđan,
Founder of Digital Hamster.

Happy Coding!