This style guide is based on this other C# style guide and expands upon it.
Our overarching goals are clarity, readability and simplicity. Also, this guide is written to keep Unity in mind.
This style guide is based on C# and Unity conventions, and discussions within the development team.
- Nomenclature
- Declarations
- Spacing
- Brace Style
- Switch Statements
- Language
- Common Patterns and Structure
On the whole, naming should follow C# standards.
Namespaces are all PascalCase, multiple words concatenated together, without hypens ( - ) or underscores ( _ ):
Namespaces are encouraged to match the folder structure.
BAD:
com.ress3dclient.scripts.structures
GOOD:
Structures.Door
Written in PascalCase. For example RadialSlider
.
Methods are written in PascalCase. For example DoSomething()
.
All non-static fields are written camelCase. Per Unity convention, this includes public fields as well.
For example:
public class MyClass
{
public int publicField;
private int packagePrivate;
private int myPrivate;
protected int myProtected;
}
BAD:
private int _myPrivateVariable
GOOD:
private int myPrivateVariable
Static fields are the exception and should be written in PascalCase:
public static int TheAnswer = 42;
Parameters are written in camelCase.
BAD:
void DoSomething(Vector3 Location)
GOOD:
void DoSomething(Vector3 location)
Single character values are to be avoided except for temporary looping variables.
Delegates are written in PascalCase.
When declaring delegates, DO add the suffix EventHandler to names of delegates that are used in events.
BAD:
public delegate void Click()
GOOD:
public delegate void ClickEventHandler()
DO add the suffix Callback to names of delegates other than those used as event handlers.
BAD:
public delegate void Render()
GOOD:
public delegate void RenderCallback()
Using built.in C# features, such as Action, is encouraged in place of delegates.
Prefix event methods with the prefix On.
BAD:
public static event CloseCallback Close;
GOOD:
public static event CloseCallback OnClose;
In code, acronyms should be treated as words. For example:
BAD:
XMLHTTPRequest
String URL
findPostByID
GOOD:
XmlHttpRequest
String url
findPostById
Access level modifiers should be explicitly defined for classes, methods and member variables. This includes defining private even though C# will implicitly add it.
Use the least accessible access modifier, except for public member that is expected to be used by other classes in the future.
Prefer single declaration per line.
BAD:
string username, twitterHandle;
GOOD:
string username;
string twitterHandle;
Exactly one class, struct, or interface per source file, although inner classes are encouraged where scoping appropriate.
All interfaces should be prefaced with the letter I.
BAD:
RadialSlider
GOOD:
IRadialSlider
Spacing is especially important to make code more readable.
Indentation should be done using spaces — never tabs.
Indentation for blocks uses 4 spaces for optimal readability:
BAD:
for (int i = 0; i < 10; i++)
{
Debug.Log("index=" + i);
}
GOOD:
for (int i = 0; i < 10; i++)
{
Debug.Log("index=" + i);
}
Indentation for line wraps should use 4 spaces (not the default 8):
BAD:
CoolUiWidget widget =
someIncrediblyLongExpression(that, reallyWouldNotFit, on, aSingle, line);
GOOD:
CoolUiWidget widget =
someIncrediblyLongExpression(that, reallyWouldNotFit, on, aSingle, line);
Lines should be no longer than 100 characters long.
There should be just one or two blank lines between methods to aid in visual clarity and organization. Whitespace within methods should separate functionality, but having too many sections in a method often means you should refactor into several methods.
All braces get their own line as it is a C# convention:
BAD:
class MyClass {
void DoSomething() {
if (someTest) {
// ...
} else {
// ...
}
}
}
GOOD:
class MyClass
{
void DoSomething()
{
if (someTest)
{
// ...
}
else
{
// ...
}
}
}
Conditional statements are always required to be enclosed with braces, irrespective of the number of lines required.
BAD:
if (someTest)
doSomething();
if (someTest) doSomethingElse();
GOOD:
if (someTest)
{
DoSomething();
}
if (someTest)
{
DoSomethingElse();
}
Switch-statements come with default
case by default (heh). If the default
case is never reached, be sure to remove it.
If the default
case is an unexpected value, it is encouraged to log and return an error
BAD
switch (variable)
{
case 1:
break;
case 2:
break;
default:
break;
}
GOOD
switch (variable)
{
case 1:
break;
case 2:
break;
}
BETTER
switch (variable)
{
case 1:
break;
case 2:
break;
default:
Debug.LogError("Unexpected value when...");
return;
}
Use US English spelling.
BAD:
string colour = "red";
GOOD:
string color = "red";
The exception here is MonoBehaviour
as that's what the class is actually called.
This section includes some rules of thumb for design patterns and code structure
Avoid throwing exceptions. Instead log and error. Methods returning values should return null in addition to logging an error
BAD:
public List<Transform> FindAThing(int arg){
...
if (notFound) {
throw new NotFoundException();
}
}
GOOD:
public List<Transform> FindAThing(int arg){
...
if (notFound) {
Debug.LogError("Thing not found");
return null;
}
}