Alexander

Alexander

hit me up
Home

Unity Attributes

Alexander - 13/12/2016

Unity’s attributes are a simple and powerful way to essentially stop you from making so many mistakes, or at least give others looking at your code or using a tool you created some idea of what it’s meant to do. This isn’t an exhaustive list but aims to cover the majority of the more commonly used ones.

 

 

AddComponentMenuAllows you to place a script anywhere in the “Component” menu, instead of just the “Component->Scripts” menu

This is purely for organising your components in the “Component” menu

Note: the function has to be non-static.

[AddComponentMenu("Example/Example Class")]
public class ExampleClass : MonoBehaviour
{
}

 

 

ColorUsage – Configure the usage of the ColorField and Color Picker for a color


[ColorUsage(bool showAlpha, bool hdr, float minBrightness, float maxBrightness, float minExposureValue, float maxExposureValue)]

 


public class ExampleClass : MonoBehaviour
{
    [SerializeField]
    [ColorUsage(false, true, 0.6f, 0.8f, 0.5f, 0.7f)]
    Color color;
}

 

 

ContextMenu – Allows you to add commands to the context menu

This is the easiest way to create a method which can be run while in edit or play mode at the command of the user, great for capturing screenshots like in the example below.

Note: the function has to be non-static.

public class CaptureScreenShot : MonoBehaviour
{
    [SerializeField]
    int SuperSample = 3;

    [ContextMenu("Capture Shot")]
    void CaptureShot()
    {
        Application.CaptureScreenshot("Screenshot_" + gameObject.name + "_" + Time.realtimeSinceStartup.ToString() + ".png", SuperSample);
    }
}

 

 

ContextMenuItem – Add a context menu to a field that calls a named method

ContextMenuItem is essentially ContextMenu but worse. Instead of adding to the drop down context menu of a component it adds a context menu when right clicking on an individual field, so far so good, but the method you assign to that field ironically has no context of which field you clicked on, so if you wanted to write a method which randomises a value – like the one below – you would need to do it once for each field you want to randomise.

So in conclusion it can only do the exact same as what ContextMenu does just in a different place in the inspector, and on top of this it calls the method by string, so if you rename the method you’ll need to update the attribute too. If you know of a way of doing more with ContextMenuItem then please let me know!

public class ExampleClass : MonoBehaviour
{
    [ContextMenuItem("Randomize Value", "Randomize")]
    [SerializeField]
    int m_Number;

    private void Randomize()
    {
        m_Number = Random.Range(0, 10);
    }
}

 

 

CreateAssetMenuMark a ScriptableObject-derived type to be automatically listed in the Assets/Create submenu

This is the easiest way to create ScriptableObjects. You just need to specify the default file name and the menu location / name and you’ll be able to create new ScriptableObjects of this type in just a couple of clicks.

Note: Unlike classes ScriptableObjects need to have a separate script for each one where the script name matches the class name. This can be particularly annoying because it’ll work fine at first but once you reload Unity it won’t find the classes and you will lose all the data saved in your .asset files.

[CreateAssetMenu(fileName = "ExampleFile", menuName = "Example/Example Class")]
public class ExampleClass : ScriptableObject
{
    [SerializeField]
    int m_Number;
}

 

 

Delayed Make a float, int, or string variable in a script be delayed

When assigning a value to the associated variable the new value will not be assigned until the user presses enter or changes focus to a different variable (as opposed to simply being able to click away).

public class ExampleClass : MonoBehaviour
{
    [SerializeField]
    [Delayed]
    int m_Number;
}

 

 

DisallowMultipleComponent – Prevents MonoBehaviour of same type (or subtype) to be added more than once to a GameObject

You will have seen the effect of this with some of Unity’s components, for example you can’t have more than one Rigidbody on a single GameObject and the use of this attribute prevents you from doing so.


[DisallowMultipleComponent]
public class ExampleClass : MonoBehaviour
{
}

 

 

ExecuteInEditMode – Any instance of the MonoBehaviour will have its callback functions executed while the Editor is not in playmode

The example below will rotate the Transform of the GameObject it is attached to to look at a Transform defined by the user in the inspector while the editor is in edit mode.

Note: the functions are not called constantly like they are in play mode.

  • Update is only called when something in the scene changed.
  • OnGUI is called when the Game View recieves an Event.
  • OnRenderObject and the other rendering callback functions are called on every repaint of the Scene View or Game View.
[ExecuteInEditMode]
public class ExampleClass : MonoBehaviour
{
    [SerializeField]
    Transform target;
    void Update()
    {
        if (target)
            transform.LookAt(target);
    }
}

 

 

HeaderAdd a header above some fields in the Inspector

This is purely for organising the inspector to make it clearer, but it can also help when looking through your code.

public class ExampleClass : MonoBehaviour
{
    [Header("Health Settings")]
    [SerializeField]
    int m_Health = 0;
    [SerializeField]
    int m_MaxHealth = 100;

    [Header("Shield Settings")]
    [SerializeField]
    int m_Shield = 0;
    [SerializeField]
    int m_MaxShield = 100;
}

 

 

HelpURLProvide a custom documentation URL for a class

This link is opened when you click on the reference icon (the book with a question mark on) of the associated component in the inspector.

You’ll only ever need this if you’re creating a tool that you’re sharing with others and have online documentation to accompany it.


[HelpURL("http://onf.re/unity-attributes/")]

 

 

HideInInspectorMakes a variable not show up in the inspector but be serialized

This is essentially used in the opposite way to the SerializeField attribute. You may want to expose a variable to other classes but not the inspector, and that’s what this is for.

public class ExampleClass : MonoBehaviour
{
    [HideInInspector]
    public int Number;
}

 

 

MultilineMake a string be edited with a multi-line textfield

Nice and simple, show a specified number of lines for a string exposed to the inspector.

Note: by default it will show 3 lines, and make sure you don’t use a number below 1 as the inspector will still try and draw it.

public class ExampleClass : MonoBehaviour
{
    [Multiline]
    [SerializeField]
    string m_Name;
}

 

 

PropertyAttributeBase class to derive custom property attributes from

If you want to create custom attributes for script variables, this is what you need to inherit from.

A custom attribute can be hooked up with a custom PropertyDrawer class to control how a script variable with that attribute is shown in the Inspector.

 

 

Preserve – Prevents byte code stripping from removing a class, method, field, or property

When you create a build, Unity will try to strip unused code from your project. You may sometimes want some code to not be stripped, even if it looks like it is not used. This can happen for instance if you use reflection to call a method, or instantiate an object of a certain class. Preserve will prevent this from happening.

public class ReflectionExample
{
    static public void InvokeFooByReflection()
    {
        typeof(ReflectionExample).GetMethod("Foo", BindingFlags.NonPublic | BindingFlags.Static).Invoke(null, null);
    }

    // No other code directly references the Boink method, so when when stripping is enabled,
    // it will be removed unless the [Preserve] attribute is applied.
    [Preserve]
    static void Foo()
    {
        Debug.Log("Bar");
    }
}

 

 

RangeMake a float or int variable be restricted to a specific range

This is useful when you have a known range for your variable. The inspector will draw a slider making it easier to use, especially with integers as the slider handle will lock to the nearest value.

public class ExampleClass : MonoBehaviour
{
    [Range(1, 10)]
    [SerializeField]
    int m_Number;
}

 

 

RequireComponentAutomatically adds required components as dependencies

If your component depends on another component on the same GameObject, you should always use the RequireComponent attribute. Below is a very common example where you want to cache a component to prevent unnecessary GetComponent calls as this is notoriously slow. By using the RequireComponent attribute we can guarantee that this GameObject will have the component we depend on, so as long as we cache the component once we never need to null check the variable because the component cannot be removed or destroyed.

Note: This can behave unexpectedly with interfaces. Say you have a public interface IMyInterface in a script called IMyInterface.cs then using RequireComponent will throw an error. If you rename your script to something else (e.g. you put your interfaces into a script names Interfaces.cs) then Unity won’t add a component when you add your dependant component (makes sense, interfaces are pretty abstract), but if you manually add something which implements IMyInterface then Unity will not let you remove it.

[RequireComponent(typeof(Rigidbody))]
public class ExampleClass : MonoBehaviour
{
    Rigidbody m_Rigidbody;

    void Awake()
    {
        m_Rigidbody = GetComponent<Rigidbody>();
    }
}

 

 

SelectionBaseMark this GameObject as a selection base object for Scene View picking

When selecting a child of GameObject marked as the selection base in the Scene View then the selection base GameObject will be selected instead.

Note: If you click on an object that is part of a prefab, the root of the prefab is selected, because a prefab root is treated as a selection base.

[SelectionBase]
public class ExampleClass : MonoBehaviour
{
}

 

 

SerializeFieldForce Unity to serialize a private field

By forcing Unity to serialize a private field we can expose it to the inspector without having to declare the variable as public. This way it isn’t unnecessarily exposed to other classes but we can still assign a value in a nice and easy way.

 

 

SpaceAdd some spacing in the Inspector

This is purely for organising the inspector to make it clearer. Spacing is in pixels.

Note: Attributes aren’t necessarily drawn in the inspector in the order they are coded! Therefore all attributes have an optional attribute to specify the order they should be drawn in the inspector. In the example below the spacing will be drawn (or I suppose to be more specific, not drawn 😉 ) before the Header because of the specified order.

public class ExampleClass : MonoBehaviour
{
    [Header("Health Settings")]
    [SerializeField]
    int m_Health = 0;
    [SerializeField]
    int m_MaxHealth = 100;

    [Space(20, order = 1)]

    [Header("Shield Settings", order = 2)]
    [SerializeField]
    int m_Shield = 0;
    [SerializeField]
    int m_MaxShield = 100;
}

 

 

TextArea – Make a string be edited with a height-flexible and scrollable text area

This is essentially the same as the Multiline attribute but you can specify the minimum and maximum number of lines for the inspector to draw. The field will expand according to the size of the text and a scrollbar will appear if the text is bigger than the area available.

public class ExampleClass : MonoBehaviour
{
    [TextArea(2, 4)]
    [SerializeField]
    string m_Description;
}

 

 

TooltipSpecify a tooltip for a field in the Inspector window

The tooltip is shown when hovering over the field it is associated to.

public class ExampleClass : MonoBehaviour
{
    [Tooltip("The maximum health the player can have.")]
    [SerializeField]
    int m_MaxHealth = 100;
}

 

Leave a Comment


Leave a Reply

Your email address will not be published. Required fields are marked *


Alexander Dudok de Wit

http://onf.re/