RealXP Lab Unity C# Style Guide
We’re sharing our internal standards to help you write cleaner, more professional code.
Jul 2, 2025
•
15 min read
This document outlines how we write and structure Unity C# code at RealXP Lab. It exists to promote readability and maintainability across our projects, and to help our externs build strong habits around clean, professional-grade code. We wanted to make it public to support the broader game dev community, especially those early in their careers.
This guide draws inspiration from Unity’s official naming and code style tips, Unity Code Style Guide by Thomas Jacobsen, and Google C# Style Guide.
Formatting guidelines
Naming conventions
PascalCase: Names of classes, structs, public fields, properties, methods, constants, enums, files, directories, namespaces
camelCase: Names of local variables, method parameters
_camelCase: Names of private fields (no
m_
,s_
, ork_
prefixes)Always explicitly specify access modifiers (e.g.
private
,public
,internal
)Variables: Use nouns. Be descriptive and avoid abbreviations. (e.g.
playerHealth
,enemyCount
,scoreMultiplier
)Units: Add units to measurable quantities (e.g.
rotationRadians
,transitionSeconds
,colorFactor0To1
)Booleans: Prefix with a verb (e.g.
isDead
,hasPowerUp
,canJump
)Enums: Use singular nouns (e.g.
WeaponType
)Bitwise enums marked with
[System.Flags]
are the exception — use plural names (e.g.AttackModes
)
Avoid redundant naming: Don’t repeat the class name in member names unnecessarily (e.g. use
Score
instead ofPlayerScore
inside aPlayer
class)Methods: Prefix with a verb (e.g.
StartGame()
,GetDirection()
)Methods returning
bool
should ask a question (e.g.IsGameOver()
,HasStartedTurn()
)
Interfaces: Prefix with capital
I
followed by a descriptive adjective or phrase (e.g.IDamageable
,ISaveable
)Namespaces: Use PascalCase without underscores or special symbols
Use namespaces to prevent naming conflicts with global or external types
Organize with dot-separated sub-namespaces based on folder structure (e.g.
Game/AI/Pathfinding/
should correspond tonamespace Game.AI.Pathfinding
)
Events:
Use verb phrases to name events, and make sure they clearly describe the state change
Use the present participle (e.g.
OpeningDoor
) to indicate an event that occurs before the action completesUse the past participle (e.g.
DoorOpened
) to indicate an event that occurs after the action has completed
Use the
System.Action
delegate by defaultPrefix event raising methods with
On
(e.g.OnDoorOpened()
)Prefix event handler methods with the subject name and underscore (e.g.
GameEvents_DoorOpened
)Only define custom
EventArgs
types when necessary
MonoBehaviour files: File name must match the MonoBehaviour class. Only one MonoBehaviour per file
Whitespace rules
Use Allman style (brace on a new line)
Indentation: 4 spaces, no tabs
Keep line lengths under 120 characters
Always use braces, even for one-line
if
/else
One declaration per line:
int health;
One statement per line
One assignment per statement
Space before flow conditions:
if (x == y)
No space between method name and parentheses:
Jump()
No space inside array brackets:
items[i]
Space after commas:
DoSomething(x, y, z)
No space after opening or before closing parentheses:
DoSomething(x)
No space after a cast:
var x = (float)y
Organization
Add
using
directives at the top of the file to avoid repeated namespace referencesAlways place
System
imports first, then sort the rest alphabeticallyStrip unused
using
directives - keep only the minimally required set
Organize class members in the following order:
Fields
Properties
Events
Unity lifecycle methods (Awake, Start, Update, etc.)
Public methods
Private methods
Nested classes or structs
Avoid
#region
unless absolutely necessary
Comments & inspector attributes
Use inline comments only when the code isn’t self-explanatory
Avoid commenting obvious logic, prefer self-documenting names and structure
Assume the what is clear from the code; use comments to explain why — intent or reasoning
Use
TODO
comments to mark follow-ups, pair it with a Notion ticket or owner when possibleStart with a capital letter and avoid periods unless it's a full sentence
Use XML summary tags for all public types (classes, structs, enums, interfaces) and their methods
Avoid leaving commented-out code in PRs, use version control.
Use one inspector attribute per line
Place attributes immediately above the member, without blank lines
Prefer
[Tooltip]
over code comments for fields exposed in the InspectorStick to common decorators:
Core:
[SerializeField]
,[Tooltip]
,[Header]
,[Space]
,[Range(min, max)]
,Min(value)]
Conditional display:
[HideInInspector]
Functionality:
[ContextMenu("Menu Text")]
,[RequireComponent(typeof(Rigidbody))]
Text areas:
[Multiline]
,[TextArea(minLines, maxLines)]
For auto-properties, use
[field: SerializeField]
to expose the backing field while maintaining encapsulation
The complete official list of Unity inspector attributes can be found in the Unity Scripting API documentation, starting with [AddComponentMenu]
.
Coding guidelines
Constants & readonly
Use
const
where possible; otherwise usereadonly
Prefer named constants to magic numbers
Collections
For method inputs, use the most restrictive collection types (
IEnumerable<T>
,IReadOnlyList<T>
, etc.)Use
List<T>
for outputs unless lazy evaluation is neededPrefer
List<T>
over arrays unless size is fixedUse arrays for multidimensional data or fixed-size containers
Avoid modifying collections while iterating — use
RemoveAll()
or collect new list
Tuples & return types
Prefer named classes over
Tuple<>
for return typesConsider return objects for complex/multi-value returns
Strings
Prefer string interpolation for readability (e.g.
$"Score: {playerScore}"
)Use
StringBuilder
for performance-critical concatenation
LINQ & delegates
Avoid long LINQ chains — prefer readability
Prefer member extension methods over query syntax (e.g.
Where()
overfrom...in...where
)Avoid
.ForEach()
on lists unless it's a one-linerAvoid LINQ in methods that run every frame (
Update
,FixedUpdate
, etc.)Use
?.Invoke()
to call delegates
Extension methods
Use extension methods only when modifying source is not possible
Prefer adding directly to class when feasible
Limit extensions to general-purpose methods
Structs vs classes
Use structs only for small, immutable, short-lived types
Default to class unless performance or memory constraints justify struct
Miscellaneous
Use
== null
for null checks overis null
orobject.ReferenceEquals(x, null)
Use
var
only when the type is obvious from contextPrefer
switch
over longif-else
chains when appropriateAvoid excessively long methods and large parameter lists
Avoid method overloading unless necessary
Example
We welcome suggestions and contributions. Reach out anytime at team@realxplab.com.