Unity Naming Conventions: C# Style Guide and Code Style Tips (2026)

Unity C# naming conventions: tidy code editor and organized project folders

Open a Unity project you wrote a year ago and you’ll find playerHP, PlayerHealth, player_health, and hp all living in the same folder, three of them referring to the same thing. Naming conventions aren’t about aesthetics โ€” they’re about making a codebase navigable by someone who didn’t write it, including future you. This guide lays out a practical, opinionated standard for Unity C# projects and the assets around them.

Quick answer

The usual Unity C# naming conventions: PascalCase for classes, structs, methods, properties, events and enum members (PlayerController, TakeDamage()); camelCase for private fields, locals and parameters (moveSpeed, or _moveSpeed if your team uses an underscore prefix); interfaces start with I (IDamageable); booleans read as questions (isGrounded, canJump). Two rules are not style but requirements: a MonoBehaviour’s file name must match its class name, and Unity message methods like Awake and OnTriggerEnter must be spelled exactly.

๐Ÿ›  Prefer a quick-reference?

The Naming Convention Reference has every rule below in a tabbed, searchable format โ€” variables, classes, methods, enums, folders, and assets โ€” for when you just need to check one thing.

Open the Naming Convention Reference →

Start From the C# Standard, Then Add Unity’s Quirks

You don’t need to invent a style. Microsoft’s C# conventions are well documented, every IDE understands them, and most of the Unity community already follows them loosely. The core rules:

  • PascalCase for classes, structs, interfaces, enums, methods, properties, events, and public fields: PlayerController, TakeDamage(), MaxHealth.
  • camelCase for local variables, parameters, and private fields: deltaTime, currentHealth.
  • Interfaces start with I: IDamageable, IInteractable.
  • No Hungarian notation: strName and fSpeed belong to a different decade.

Unity then adds a handful of rules that aren’t stylistic at all โ€” break them and things silently stop working.

The Unity Rules That Actually Break Things

The file name must match the MonoBehaviour class name

A script called EnemySpawner.cs must contain public class EnemySpawner : MonoBehaviour. If they differ โ€” even by case โ€” Unity can’t attach the component and you’ll get the dreaded “the associated script can not be loaded” message. This is the number-one cause of the problem covered in our missing script references guide.

Unity message methods must be spelled exactly

Awake, Start, Update, FixedUpdate, OnTriggerEnter, OnCollisionEnter2D โ€” Unity calls these by name via reflection. Write onTriggerEnter or OnTriggerEntered and the compiler won’t complain; the method just never runs. Consistent PascalCase for all methods makes these typos far less likely.

Serialized fields show up in the Inspector by name

A private field marked [SerializeField] private float moveSpeed; appears in the Inspector as “Move Speed” โ€” Unity splits the camelCase for you. This is why the common Unity pattern is camelCase for serialized private fields, with or without an underscore prefix (_moveSpeed also renders cleanly). What you should avoid is exposing public fields just to see them in the Inspector; [SerializeField] private gives you the same result without leaking write access to every other script.

Variables and Fields

Kind Rule Example
Private field camelCase, optional _ prefix โ€” pick one project-wide _health or health
Serialized private field camelCase + [SerializeField] [SerializeField] private float jumpForce;
Property PascalCase public float Health { get; private set; }
Constant PascalCase (or ALL_CAPS if the team prefers) const int MaxPlayers = 4;
Static PascalCase public static GameManager Instance
Boolean Reads as a question: is / has / can / should isGrounded, canDoubleJump

The underscore-prefix debate is the one that generates the most heat and matters the least. _health makes private fields instantly distinguishable from locals and parameters without this.; plain health is what most Unity tutorials use. Choose, write it down, move on.

Classes, Structs, and Interfaces

  • Classes are nouns: InventorySystem, EnemySpawner, not ManageInventory.
  • ScriptableObjects get a suffix that says what they hold: WeaponData, LevelConfig, AudioSettings. It’s immediately clear in the Project window that these are data, not behaviour.
  • Abstract base classes often carry a Base prefix (BaseEnemy) so subclasses read naturally (FlyingEnemy : BaseEnemy).
  • Custom editors match their target plus Editor: EnemySpawnerEditor. Same for PropertyDrawers (RangeAttributeDrawer).
  • Structs follow class rules and should be small, immutable value bags: DamageInfo, GridPosition.

Methods

  • Verb first: TakeDamage(), SpawnWave(), CalculateTrajectory().
  • Bool-returning methods read as questions: IsInRange(), CanAfford(), TryGetTarget(out Transform target). The Try prefix specifically signals “returns false instead of throwing”.
  • Coroutines get a Routine or Coroutine suffix so a call site like StartCoroutine(FadeOutRoutine()) is self-describing.
  • Async methods end in Async: LoadSceneAsync(). This matches the .NET convention and Unity’s own Awaitable APIs.
  • Event handlers: either HandlePlayerDied() or OnPlayerDied(). Be aware that On-prefixed names collide visually with Unity’s message methods, which is why some teams prefer Handle.

Enums, Events, Delegates, and Namespaces

  • Enum types are singular nouns, members PascalCase without a prefix: WeaponType.Sword, not WeaponType.WT_SWORD. Flags enums are plural: [Flags] enum DamageTypes { Fire = 1, Ice = 2 }.
  • C# events are named for what happened, usually past tense: PlayerDied, HealthChanged. Delegates take a Handler suffix: DamageHandler.
  • UnityEvent fields are serialized, so they follow the camelCase field rule: [SerializeField] private UnityEvent onHealthChanged;
  • Namespaces follow Company.Project.Feature: DevForge.Combat, DevForge.UI.Menus. Wrapping your code in a namespace also prevents collisions with Asset Store packages, which is a real problem once a project has twenty of them.
  • Tags, layers, and animator parameters are strings, and strings are typo magnets. Put them in a static class of constants โ€” Tags.Enemy, AnimParams.IsRunning โ€” so CompareTag("Enemey") becomes a compile error instead of a runtime mystery.

Assets and Folders

Code conventions are half the story. A project with clean C# and a Project window full of New Material 3 and Untitled Scene (2) still isn’t navigable.

Asset Rule Example
Prefab PascalCase, named for the thing EnemyGrunt.prefab
Material Object + _Mat Rock_Mat.mat
Texture Object + map type Rock_Albedo.png, Rock_Normal.png, Rock_Metallic.png
Animation clip Character + action Player_Jump.anim
Animator controller Character + _AC Player_AC.controller
Scene Numbered when order matters 01_MainMenu.unity, 02_Level1.unity
Audio Category prefix SFX_Footstep_Grass.wav, MUS_MainTheme.ogg, VO_Intro_01.wav

For folders, organize by feature first, then by type. Assets/_Project/Player/Scripts, Assets/_Project/Player/Prefabs, and Assets/_Project/Player/Art keep everything about the player in one place; a top-level Scripts/ folder with two hundred files in it does not scale. The leading underscore on _Project sorts it above Unity’s own folders and every Asset Store import, which should live untouched in Assets/ThirdParty/.

Enforce It With Tooling, Not Willpower

Conventions that depend on people remembering them last about two sprints. Conventions the IDE enforces last forever. Commit an .editorconfig at the root of the repository โ€” Rider, Visual Studio, and VS Code all read it โ€” and the editor will flag violations as you type. A minimal one for the rules above:

root = true

[*.cs]
indent_style = space
indent_size = 4
dotnet_naming_rule.private_fields_camel.severity = warning
dotnet_naming_rule.private_fields_camel.symbols = private_fields
dotnet_naming_rule.private_fields_camel.style = camel_case_style
dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private
dotnet_naming_style.camel_case_style.capitalization = camel_case

Pair it with the naming section in your project README, and make consistency part of code review. If you’re setting up version control for the first time, our Git for Unity guide covers where the .editorconfig and .gitignore belong.

None of these rules are sacred. What matters is that your project has a rule for each case, that it’s written down, and that the tooling catches drift before a reviewer has to. Pick your style today โ€” the reference is there whenever you need to double-check one.

๐Ÿ“š Want to go beyond naming?

Consistent names are the first step toward maintainable code. Game Programming Patterns by Robert Nystrom is the natural next read. It’s on our list of the best books for game developers, along with two C# fundamentals picks.

See our recommended books →

Comments

One response to “Unity Naming Conventions: C# Style Guide and Code Style Tips (2026)”

  1. […] The convention most studios follow: fields are private, and anything that needs editing in the Inspector gets [SerializeField]. Expose data to other scripts through properties or methods. It’s the same principle as in our C# naming and style guide. […]

Leave a Reply

Your email address will not be published. Required fields are marked *