UNITY-UFS Course

Unity Script++

This course is a gathering of notes and tips to make your scripts cleaner, and more user-friendly.


Coding conventions

Methods

The name of a method should start with an uppercase
- private void myMethod() {}
+ private void MyMethod() {}
You should explicitly add the qualifier
- void MyMethod() {}
+ private void MyMethod() {}

Attributes

Private attributes should start with an underscore (_), or ends with an underscore (up to you). You can use either snake case, or camel case.
- private int myAttribute;
+ private int _myAttribute;
Attributes should be private or protected
- int myAttribute; // not private (implicit)
- public int myAttribute; // not public
+ protected int _myAttribute; // either explicit protected
+ private int _myAttribute; // or explicit private
Serialized variables (explained later) or public variables (bad πŸ™„) should start with a lower case
- public int _myAttribute;
- [SerializeField] private int _myAttribute;
+ public int myAttribute;
+ [SerializeField] private int myAttribute;

Performances

"If" must not be the last instruction
- private void MyMethod()
- {
- 	// some code here (optionnal)
- 	if (something) {
- 		// some code here
- 	}
- }
+ private void MyMethod()
+ {
+ 	// some code here (optionnal)
+ 	if (!something) return;
+ 	// some code here
+ }

Serialize Field

When creating a Script, it's shown) in the inspector. You can add (we are saying "expose" too) fields inside the inspector too, to allow someone (or yourself) to easily change some values/parameters.

The bad way to do this, is to set an attribute public. Indeed, as a "side effect", it will be shown inside the editor, but it also means that any other class knows this attribute, and this may lead to problems later.

The right way to do this, is to declare a serialized field.

[SerializeField] private int number = 0;
// or on two lines 😢
[SerializeField]
private int number = 0;
// or πŸ™„ (bad πŸ‘Ž)
public int number = 0;

Resulting in

Create field inspector unity

Pro tip: Unity will show the right field, according to the type of the attribute. You can request a game object, or a component, and in both cases, you will be able to drag and drop a game object from the hierarchy, to the field. You can also use the small circle with a dot, to browse values for this field (Unity pick value).


Serialize Field : basic

Rename a Serialize Field πŸ‘
[SerializeField]
[FormerlySerializedAs("oldName")] private int number = 0;
Tooltips 😎

Maybe, the name of your attribute isn't providing enough information for the user to know what should be in this field. You should always add a Tooltip, shown when the user is hovering (=mouse stay over) the field.

[Tooltip("Some description blah blah blah")]
[SerializeField] private int number = 0;

Unity Serialize Field - tooltip (mouse hovering "key")

Pro tip: this is not an excuse to give bad names to your fields (as I did with "number" or "key").

Headers ✨

You can make categories with Headers. This is a great way of sorting your serialized fields, if you got a lot of them.

[Header("Some header")]
[SerializeField] private int a;
[SerializeField] private float b;
[SerializeField] private bool c;

Unity Serialize Field - header

Spaces ✨✨

If headers aren't enough, you can add some spacing too.

[Header("Some header")]
[SerializeField] private int a;
[Space(2)]
[Header("Some header")]
[SerializeField] private int b;

Unity Serialize Field - spacing

New Menu πŸš€

When clicking on "adding component", you got a list of menus such as "Audio", ... You can add a new menu here πŸš€!

// this is a path, you can subfolders (=nested menus) with /
[AddComponentMenu("CubeMaster/Movement")]
public class MovementManager : MonoBehaviour {}

Unity Serialize Field - New Menu1 Unity Serialize Field - New Menu2

Pro tip: [Space(2)][Header("name")] is the same as [Space(2), Header("name")]


Serialize Field: more

General πŸ› 
CodeEditor/Description
[HideInInspector] public float hide;

No field "hide".

[RequireComponent(typeof(Collider))]
// [RequireComponent(typeof(Collider), typeof(Rigidbody))]
public class SomeClass : MonoBehaviour {}

You can't add this class as a component of a game object, if this class does not have a collider.

[DisallowMultipleComponent]
public class SomeClass : MonoBehaviour {}

You can't have more than one instance of this component per game object.

[HelpURL("https://memorize.be/games")]
public class SomeClass : MonoBehaviour {}

You can set the link opened when clicking on the "?" mark, next to the 3 dots, to remove a component.

[ContextMenuItem("reset", "ResetIntWithMenuItem")] 
public int intWithMenuItem;
private void ResetIntWithMenuItem()
{
	intWithMenuItem = 12;
}

When using your left-click on a field, you can add fields in the context menu. If you want to add something for the class, check ContextMenu.

Attributes Unity - Context

// using System; // for Serializable
[Serializable]
public class NestedClass // <=> struct
{
	public int nestedAttribute; 
}
[SerializeField] private NestedClass nestedClass;

You can make a dropdown nested inside your component, as other native components do. The class must be Serializable, then simply give the Serializable class as the type of the field.

Attributes Unity - Nested

private enum Axis
{
	[InspectorName("X-axis")] X, 
	[InspectorName("Y-axis")] Y
}
[SerializeField] private Axis axis = Axis.X;

You can use this to rename the values of your enum in the inspector. It does not work for attributes 😭.

Attributes Unity - InspectorName

Numbers πŸ”’
CodeEditor/Description
[Min(10)] public int speed = 15;

Attributes Unity - min

If the value is lower than min, then value = min.

[Range(0, 1)] public float volume;

Attributes Unity - range

Strings πŸ“š
CodeEditor/Description
[Multiline(2)] public string text = "";

Attributes Unity - multiline

// or [TextArea( minLines, maxLines )]
[TextArea] public string textarea = "";

Attributes Unity - textarea

You got way more attributes, you can

  • use SelectionBase to a class (even if you are not showing it in the editor), to pick whether this class should be selected (no attribute, default), or the base (this attribute)
  • add an entry in the preferences with SettingsProvider (new version of PreferenceItem)
  • add an entry in the toolbar with MenuItem
  • add an entry in the assets list with CreateAssetMenu (attached to a class extending ScriptableObject)
  • make this component show up when selecting multiples game objects with CanEditMultipleObjects

More?