- Commit titles should start with a capital letter and be strictly one sentence long (no fullstop is needed).
- Commit messages must be phrased in present tense.
- Additional content should be placed in the commit description.
- Identifiers and other names should be enclosed in backticks.
Example(s):
CORRECT:
Add `PlayerController` script
Complete basic 2D movement and jump.
WRONG:
Added PlayerController script.
- All commits need to work without further modifications.
- When someone checkouts a commit (with a detached HEAD), the project should still compile and run mostly free of any problems (semantic or otherwise).
- Check the build before making any commits and pushes.
- Commits should be small in size and self-contained.
- Commits should as best as possible not do more than 1 "big" thing as once.
-
A line should be strictly capped at a length of 80 (range: [0, 80]).
-
Manually wrapping is to be done should a line need more than 80 characters, as such:
- Operator to be left at the previous line.
- Where
L
is the original line,L + 1
should have a+1
indent relative toL
. - When more than 1 round of wrapping is needed,
L + 2
and beyond should keep the same indentation level asL + 1
.
Example(s):
SuperDuperLongFunctionCall(veryVeryVeryVerboseArg1, veryVeryVeryVerboseArg2, veryVeryVeryVerboseArg3, veryVeryVeryVerboseArg4);
- Explicit access modifier for all declarations, except within interfaces.
- Unity message methods should always be private.
- Serialized fields should always be private.
- Should a public variable be needed, always make it a property.
Example(s):
// WRONG
string _someName = "Name";
// WRONG
void Update()
{
...
}
// CORRECT
private void Update()
{
...
}
- All comments to start with
//
(per line needed). - Multi-line comments (
/*
and*/
) should not be used. - The comment must be preceded by strictly 1 space character.
- The first character after the space should be captialized should it be [a-z].
- Comment line horizontal length should be around the same as the target code block.
- If the comment references an identifier in the code surround the identifier in backticks.
Example(s):
// WRONG
// This is a very long and detailed comment as to why I have a bool here
private bool _extraBool = false;
// CORRECT
// This is a very long and detailed
// comment as to why I have a bool here
private bool _extraBool = false;
private void Foo()
{
// WRONG
// Call Bar to init ...
// CORRECT
// Call `Bar` to init ...
Bar();
...
}
- Source files and Assets:
PascalCase
. - Game object names:
PascalCase
. - Types:
PascalCase
. - Private variables (including serialized ones):
_camelCase
(note the leading underscore). - Functions, properties and public variables:
PascalCase
. - All other identifiers:
camelCase
.
- Leave a line between using groups.
System
usings should be first.Unity
usings should be next.TMPro
usings belong together withUnity
.- Order by semantics, then by length.
- Superfluous
using
to be removed.
Example(s):
using System;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
- Fill in both menu name and file name.
Example(s):
[CreateAssetMenu(menuName = "Scriptable Object/Entity/Creature",
fileName = "New Creature")]
public class Creature : Entity
{
...
}
- Braces should always be on its own new line, never omit it.
Example(s):
// CORRECT
if (condition)
{
...
}
// WRONG
if (condition) ...
// WRONG
if (condition)
...
- All attributes to have their own line.
- Rule 3 still applies for attributes.
- Header attributes should have 1 empty line above and below it, except when the top or bottom is an opening or closing brace.
Example(s):
public bool SomeOtherJunk = true;
[Header("Vitals Drain Rate")]
[SerializeField]
[Range(0f, 5f)]
private float _hungerDrainPerSec = 1f;
- Keep to 1 type declaration per source file.
- Nested types can be allowed depending on circumstance.
-
Nested types should be first regardless of visibility.
-
Next, variables and properties to be declared in the following order:
- Properties first then variables.
- Public (should have 1 empty line above and below it, except when the top or bottom is an opening or closing brace).
- Private and serialized (whole block should have 1 empty line above and below it, except when the top or bottom is an opening or closing brace).
- Private and for internal use only (group all together with the whole group having 1 empty line above and below it, except when the top or bottom is an opening or closing brace).
-
Lastly, methods to be declared in the following order:
- Public.
- Protected.
- Private.
Example(s):
public class PlayerVitals : MonoBehaviour
{
public class NestedType
{
...
}
public int IntProp { get; private set; }
public float StinkyFloat = 0f;
[SerializeField]
[Range(0f, 5f)]
private float _hungerDrainPerSec = 1f;
private GameReset _gameReset;
private UIManager _manager;
public void PublicFunction()
{
...
}
protected void ProtectedFunction()
{
...
}
private void Update()
{
...
}
}
- An assert message should be present for most of the cases.
Example(s):
private void LoadKeyframes(List<int> indices)
{
Assert.IsTrue(indices.Count > 0,
"`indices` should not be empty as total " +
"keyframes must be greater than 0");
...
}
- Use of labels such as
TODO
,FIXME
,SAFETY
and any others where appropriate. - Format them as such
// NAME_OF_LABEL (NAME_OF_PERSON): Comment description
.
Example(s):
// TODO (Cheng Jun): Add descriptive comments here outlining how this works
// FIXME (Chris): A valid input is assumed here, add a validation check
// SAFETY (Brandon): The index is presumed to be in range, due to ...
- Branch names should only contain lowercase letters (numbers may be permitted where appropriate) and be delimited by a single dash (
-
). - Main branch should be the
dev
branch. - Do all development on the respective topic or feature branch, else commit to the
dev
branch. - Do not create branches based on members (branch name should not contain anyone's name).
main
branch should only contain "release ready" builds that have been sufficiently tested.
Example(s):
this-is-a-valid-branch-name
This-Is_not-a_valid_branch-name
- All built-in and other components should be before script components.
- Prefer the use of semantic generic argument identifiers
Example(s):
// WRONG
public class StateMachine<T, U>
{
...
}
// CORRECT
public class StateMachine<TSelfID, TStateID>
{
...
}