Learn Unity Editor Scripting: Attributes [Part 1]

No Such Dev
6 min readOct 7, 2020

--

In this post I’ll show you how to use the attributes defined in Unity assemblies to change how Unity Editor interacts with your components. Attributes are versatile and easy to use. You don’t need to write any editor-specific code. You just need to annotate your C# fields and classes with attributes.

This article is part of a series in which I explain all the techniques for extending the Unity Editor. See the overview post here.

Prerequisite: You need to know C# programming and be familiar with Unity Editor to benefit most from this post.

There is an accompanying Unity project. I highly recommend downloading it and trying the topics as you read them here. Seeing the examples in action makes them stick to your brain.

Getting Started with the Project

Download the github project linked above. There are folders corresponding to different posts in this series. Each folder is the repository is the same project with additions from the previous post. So for this article which is part1 you should start with arena-0 and at the end of the post, if you make all changes as described, your project should look like arena-1.

The project is very simple and has just a few scripts. Run the project. You can use the arrow keys to move around and your goal is to clear the arena of obstacles. When all obstacles are cleared or the player falls off the arena, the game ends and there is a message in the console indicating that.

Attributes

Attributes in C# let you annotate different programming elements (fields, methods, classes, etc.) and query them using Reflection. Unity Editor uses them to allow easy modification for some common scenarios.

[SerializeField]

This attribute tell Unity that this field should be serialized with the component. Note that initially the fields in PlayerController class are declared public . That’s why Unity serializes them and the Inspector window shows them.

T
Fields for “PlayerController” component are shown in the Inspector.

Let’s mark our field private as they should be for better coding practices. This time the Inspector for PlayerController shows no fields.

However declaring fields public just so they show up in the Inspector is not the right thing to do. Let’s make these fields private which makes our code cleaner. But now these fields don’t show in Inspector.

No fields are shown in the Inspector for “PlayerController” component.

Adding the [SerializeField] attribute will make Unity serialize the fields and show them in Inspector even though they are private .

Now the Inspector window looks exactly as before.

[Serializable]

You might have noticed that the specialAbility field wasn’t shown in the Inspector. Unity can only serialize custom classes that have the Serializable attribute. The rules for what Unity can handle are explained here.

Let’s go ahead and annotate our SpecialAbility class with [Serializable] attribute.

Now the Inspector will show the specialAbility field and let’s us edit it!

“Special Ability” field is now shown.

[HideInInspector]

By default Unity shows all the serialized fields for each components. However, being serialized and being shown in Inspector are two different things.

being Serializable and matching the criteria for being serialized by Unity are prerequisites for being shown in Inspector. But we can hide some of those fields in Inspector for example if we want to set the values only from code.

Let’s add the HideInInspector attribute to the mass field.

Now the Inspector window will not show the mass field. Note that the field still gets serialized and the mass that is set at Edit time (for example from code in OnValidate) will be written to disk.

“Mass” field isn’t shown in Inspector window anymore.

We however want to be able to change the mass from our PlayerController inspector. It may seem redundant since we can directly change the mass in the RigidBody component. Keeping everything in one place makes making modifications easier. You have less chance of accidentally messing up the level setup if you avoid the RigidBody component altogether. So let’s remove the HideInInspector from the field.

[Header]

We don’t have too many fields in this sample, but in larger scripts with more fields, it makes sense to group them so that we find them more easily. In our sample Colorand Texture fields are cosmetic whereas the other fields affect the game play. Let’s group our fields into General and Visual using the [Header] attribute.

Note that the header attribute takes a string parameter which is the header title.

Now you should see the fields grouped in the Inspector.

“General” and “Visual” headers help us organize the fields into groups.

[Tooltip]

You can add a tooltip text to any field in Inspector. Let’s go ahead and add tooltips to both our color and texture fields.

Now if you hover your mouse over the label for these fields, you will see the tooltip for it.

Hovering mouse over “Color” and “Texture” fields will show the tooltip for those fields.

[DisallowMultipleComponent]

Currently we could mistakenly add two PlayerController components to a single GameObject.

We can add the [DisallowMultipleComponent] attribute to our PlayerController class.

Now Unity Editor will not allow us to add the duplicate component and shows us an error message instead.

Unity Editor will not allow adding multiple “Player Controller” components to the same Game Object.

Note that it is still possible to add duplicate components from code. Only adding it through the Editor UI is prohibited.

[Space]

We can add extra vertical empty space between fields to further separate them. Let’s add a 10 pixel space before the SpecialAbility field.

And here is how the Inspector looks like after:

There is some empty space before the “Special Ability” field.

[TextArea]

By default the Inspector shows a single line text box for string fields. In our GameManager components, we want a longer text for the intro text. This is the text that shows in the middle of the screen when the level starts and explains to the user what they should do.

By adding the [TextArea] attribute to that field, we get a larger text area in the inspector window.

intro field now has a large text area instead of the single line text field.

[Range]

mass, speed and size are all float fields. Often we want to limit these values to a certain range. the [Range] attribute helps us with that.

Now in addition of the default text field, we can select the value from a slider. Range also works with int fields.

Mass, Speed and Size now use a slider UI.

Conclusion

We went through some of the more common attributes for modifying the Inspector window and how the Unity Editor handles our classes. All we needed to do was adding attributes to our existing code.

There are many more attributes that Unity Editor understands by default. You can see them here on the left panel.

Attributes are very flexible. In fact, we can make our own custom attributes and use them in our Editor Code (in Property Drawers and Custom Inspectors and Editor Windows) which we will learn about later on!

Next

If you have any questions and suggestions about this post, feel free to leave a comment.

Follow me to get notified of my new posts. I am an indie game developer and regularly write tutorials, tips and tricks and stories about game dev, programming and Unity.

If you find this tutorial useful, please support me on Patreon. It takes a good amount of time to write these tutorials and your support will keep me going. Thank you!

Next we will learn how to create Property Drawer. They let us write code to show our own GUI in Inspector window for our custom data types or certain fields in our components.

--

--

No Such Dev

Software Engineer | Indie Game Developer | Founder of No Such Studio. Follow me to learn how to make video games with Unity. http://www.nosuchstudio.com