Skip to main content

Unity Coding Standards

Introduction

Establishing a coding standard is essential to the long-term health of a project. While there are certain
general rules that are almost universally good to follow, other rules can be a matter of personal
preference.

However, the most important thing is that all of these rules are followed, once established.

Over time, the codebase will develop a sort of “second language” that will allow current engineers to
read and understand new code easily, and new engineers to ramp-up and familiarize themselves with
the codebase quickly.

It may seem like some rules put up some annoying hoops for you to jump through just to get a simple
feature working. That’s good. These hoops may seem arduous, but they will force you to write good
code.

Good code is:

  • Easily readable and understandable, especially to other engineers who have not written it
  • Flexible, and easy to modify or add to
  • Sufficiently optimized for the needs of the project
  • Written to expose appropriate properties for non-developers to tinker with in a way that makes
    sense (in Unity)

Good code is NOT:

  • Written with a motivation to have as few lines and characters as possible
  • Over-optimized to the point where the code becomes over-engineered and difficult to parse for
    non-authors
  • Covered in comments explaining all aspects of it in detail. Reading the code should be
    self-explanatory (if written properly) and comments should only be used to explain parts of code
    that necessitate the use of more advanced/confusing practices.

With all of this being said, here are the rules that have been established for Unity projects as of January
2024 (projects started before this date may not fully adhere to them).

Code Formatting

Indentation

Rule: Code should be indented with 4 spaces, not tabs. If you’re not a fan of mashing the spacebar

(understandably), you can configure Visual Studio to automatically replace any tabs you have with the
designated number of spaces instead.

Motivation: This is mostly personal preference, however in my experience using spaces tends to make
files and diffs easier to read on Git.

Example:

Good Coding Example: IndentationBad Coding Example: Indentation

Spaces

Rule: Each distinct component of a line of code (variable name, expression character, keyword, etc.)
should be separated by a space.

Motivation: Spreading out elements of code with a single space can make it easier for engineers to
parse code without it feeling claustrophobic (this is admittedly a personal preference).

Example:

Good Coding Example: SpacingBad Coding Example: Spacing

Brackets

Rule: All brackets should be on a newline, and should not be put on the same line as a class name,
conditional statement, etc.

Motivation: Placing brackets on newlines makes it easier for developers parse code that is particularly
nest-y. Compartmentalizing code based on its indentation is easier to do when the brackets are
essentially used as “markers” for this separation.

Example:

Good Coding Example: BracketsBad Coding Example: Brackets

Loops and If Statements

Rule 1: All loops and if statements, even if they execute a single line of code, should be enclosed in
brackets.

Motivation: There is no functional purpose for writing single-line loops or if statements without
brackets other than to save a trivial amount of characters and lines. Instead, it makes it more difficult to
compartmentalize code while reading it, and makes it easier to accidentally break if another engineer
tries to modify it (and forgets to add brackets that they assumed would be there).

Example:

Good Coding Example: Loops and Ifs StatementsBad Coding Example: Else If Statements

Else If Statements

Rule: Else If and Else statements should be started on a newline, and should not be defined on the
same line of a closing bracket.

Motivation: Formatting statements like this makes it easier for engineers to parse and mentally
compartmentalize code, which is worth sacrificing a trivial number of extra lines.

Example:

Good Coding Example: Else If StatementsBad Coding Example: Else If Statements

Compound Conditional Statements

Rule: If a loop or if statement evaluates more than one condition at once, enclose those conditions with
parentheses.

Motivation: Mostly personal preference. However, enclosing each condition in a compound statement
makes it easier for engineers to determine which values are involved with which statement at a glance,
especially for more complicated compound statements.

Example:

Good Coding Example: Compound Conditional StatementsBad Coding Example: Compound Conditional Statements

Private Values

Rule: By default, C# designates all variables and functions as “private” unless designated otherwise by a
keyword such as “public” or “protected.” However, we will be explicitly designating our values using the
“private” keyword whenever it is applicable.

Motivation: This is once again a matter of personal preference. However, using the “private” keyword
often results in code “lining up better” (particularly with lists of variables) and the color-coding that is
applied to most development environments can make these values easier to find, all of which results in
“easier to read” code.

Example:

Good Coding Example: Private ValuesBad Coding Example: Private Values


Serialized Variables

Rule: When exposing a variable in Unity using the [SerializeField] Attribute, put it on a newline above
the desired variable.

Motivation: This can make lists of variables easier to parse, as it keeps all of the variable declarations at
the same indentation. It also makes it easier to see which variables are exposed in the Unity Inspector at
a glance.

Example:

Good Coding Example: Serialized VariablesBad Coding Example: Serialized Variables

Code/Naming Conventions

Loops and If Statements

Rule: Loops and conditional statements should be defined as explicitly as possible using two-sided
expressions such as ==, >=, and <=. Avoid using != when possible, as well as evaluating a Boolean or
other values by simply negating it with a !.

Motivation: Standardizing the way loops and conditional statements are defined lowers the risk of other
engineers misinterpreting the condition. It also makes code easier to follow, because the purpose of the
condition is explicitly described, and the data types of the variables involved are easy to identify.

Example:

Good Code/Naming Convention Example: Loops and If StatementsBad Code/Naming Convention Example: Loops and If StatementsBad Code/Naming Convention Example: Loops and If Statements

Variables

Ideally, if an engineer is looking over code written by someone else, they should be able to immediately
comprehend what each variable represents, as well as its scope within the context of the code they see
it in. With that in mind, we should strive to adhere to the following conventions when declaring and
referencing variables.

Naming
Variable names should describe as accurately as possible the value it contains, regardless of how long it
is. Ideally, an engineer will be able to understand what the variable is used for by simply reading the
name, and not having to search for references of it to see how it’s used in context.

Avoid abbreviating any words in a variable name, especially when it is not clear what word the
abbreviation is meant to replace. The only exception to this rule is for variables that are declared solely
to be incrementors in a for loop (ex: for (int i = 0; i < 10; i++))

Code/Naming Convention Examples: Variables

Public Class Variables

Variables declared as public with a class-wide scope should be written in camelCase.

When referencing these variables within their declared class, they should be prefaced using the “this.”
identifier to indicate their class-wide scope.

Good Code/Naming Convention Example: Public Class Variables

Protected Class Variables

Variables declared as protected with a class-wide scope should be written in camelCase, then ended with
an underscore.

When referencing these variables, they should be prefaced using the “this.” identifier, to indicate their
class-wide scope.

Good Code/Naming Convention Example: Protected Class Variables

Private Class Variables

Variables declared as private with a class-wide scope should be prefaced by an underscore, then written
in camelCase.

When referencing these variables, they should be prefaced using the “this.” identifier, to indicate their
class-wide scope.

Good Code/Naming Convention Example: Private Class Variables

Function Parameters

Function parameters should be prefaced by an underscore, then written in camelCase.

Good Code/Naming Convention Example: Function Parameters

Function Variables

Local variables declared within a function should be written in camelCase.

Good Code/Naming Convention Example: Function Variables

Static Variables

Variables declared as static should have each word in its name capitalized.

When referencing static variables, always preface the variable name with the name of the owning class
(even when you reference the static variable within the owning class).

Good Code/Naming Convention Example: Static VariablesBad Code/Naming Convention Example: Static Variables

Constant Variables

Constant variables should be written in ALL CAPS, with underscores separating each word in the name.

When referencing constant variables, follow the same pattern as private, public, and static variables with
regards to prefacing identifiers.

Good Code/Naming Convention Example: Constant Variables

Functions

Function names should describe its purpose as accurately as possible. Ideally, an engineer should be
able to know what a function is supposed to do within a block of logic without having to look at its
definition. With this in mind, functions should be declared with the following conventions:

  • Each word in a function name should be capitalized.
  • Avoid using abbreviations in a function name. Long descriptive names are better than short,
    abbreviated names.
  • Whenever a function is referenced within the scope it was declared in, it should be prefaced
    with the “this.” identifier.
  • Whenever possible, function names should start with a verb that describes what the function
    “does” (Ex: Get, Set, Access, Calculate, etc.)
    • If you find it difficult to name a function with a single verb, check to see if the function
      can actually be split into multiple smaller functions.

Classes

Class names should describe its purpose as accurately as possible. Ideally, an engineer should be able to
understand the purpose of a class and have a relatively good idea of the functionality it contains by
simply reading its name. With this in mind, classes should be declared using the following conventions:

  • Each word in a class name should be capitalized.
  • Avoid using abbreviations in a class name. Long descriptive names are better than short,
    abbreviated names.

Misc. Suggestions

The following are more subjective suggestions rather than hard-and-fast rules. However, you will likely
find that following them will result in code that is cleaner and easier to read and understand at a glance.

Compartmentalize Complex Logic in a Function

If you are writing an algorithm (or part of an algorithm) that is several lines of code long, consider
putting all of the specific logic into its own (properly named) function. Even if the function is only ever
called once, it will be extremely helpful for other engineers (or yourself, in the future), as they will not be
unnecessarily forced to parse and understand how a complex process works if they don’t have to.

Instead, they can read a descriptive function name, trust that it does what it says, and move onto other
parts of the code that they actually intend to investigate or modify.

Make Use of the [HideInInspector] Attribute

If a public variable is not meant to be set or modified in the Unity inspector, denote it with the
[HideInInspector] attribute before its declaration. This will not only make components in the Unity
editor far less cluttered, but it will also make it explicitly clear to other team members tinkering with the
project which values are “allowed” to be experimented with without causing any technical issues.

Don’t Be Afraid to Copy

When in doubt about how parts of code should be formatted or named, it’s best to emulate what you
already see in the codebase. In the end, it’s better to have a consistent coding style across the project
than it is to have a “correct” style (a futile endeavor to pursue). Alternatively, you can simply ask
another engineer on the team for advice on naming/formatting.