Last active
June 9, 2025 09:19
-
-
Save talenguyen/510222faab6e7bef9f845f0f2f980704 to your computer and use it in GitHub Desktop.
Unity C# Style Guide Template
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; // For List | |
| using UnityEngine; | |
| // GLOBAL ENUM EXAMPLE | |
| /// <summary> | |
| /// Describes the state of the game. | |
| /// </summary> | |
| public enum GameState // Pascal case, singular noun | |
| { | |
| MainMenu, // Pascal case | |
| Playing, | |
| Paused, | |
| GameOver | |
| } | |
| // INTERFACE EXAMPLES | |
| /// <summary> | |
| /// Interface for objects that can be killed. | |
| /// </summary> | |
| public interface IKillable // Prefix with "I" and use an adjective | |
| { | |
| bool IsDead { get; } // Property asking a question | |
| void Kill(); // Method starts with a verb | |
| } | |
| /// <summary> | |
| /// Interface for objects that can take damage. | |
| /// </summary> | |
| public interface IDamageable<T> // Prefix with "I" and use an adjective | |
| { | |
| void Damage(T damageTaken); // Method starts with a verb, camel case parameter | |
| } | |
| /// <summary> | |
| /// Example MonoBehaviour class following the style guide. | |
| /// </summary> | |
| public class GameManager : MonoBehaviour, IKillable // Pascal case noun for class name | |
| { | |
| // FIELDS | |
| // Prefer [SerializeField] over public attributes | |
| [SerializeField] private float _spawnInterval = 2.0f; | |
| [SerializeField] private int _maxEnemies = 10; | |
| [SerializeField] private bool _canSpawnEnemies = true; // Prefixed with a verb | |
| private int _currentEnemyCount; // private field with _ prefix, camel case, noun | |
| private float _timeSinceLastSpawn; | |
| private bool _isGameActive; // private boolean with _ prefix, prefixed with a verb | |
| // Example of a public field (less preferred than [SerializeField] for inspector exposure) | |
| public string GameVersion = "1.0.0"; // Pascal case for public field | |
| // PROPERTIES | |
| /// <summary> | |
| /// Gets the current number of enemies. Read-only. | |
| /// </summary> | |
| public int CurrentEnemyCount => _currentEnemyCount; // Expression-bodied property for single line read-only | |
| /// <summary> | |
| /// Gets or sets the maximum number of enemies. | |
| /// </summary> | |
| public int MaxEnemies | |
| { | |
| get => _maxEnemies; // Explicitly implementing getter | |
| set => _maxEnemies = Mathf.Max(0, value); // Explicitly implementing setter | |
| } | |
| /// <summary> | |
| /// Indicates if the game is currently active. | |
| /// </summary> | |
| public bool IsGameActive // Asks a question | |
| { | |
| get { return _isGameActive; } | |
| private set { _isGameActive = value; } // Auto-implemented property syntax for other cases | |
| } | |
| // IKillable implementation | |
| public bool IsDead => _currentHealth <= 0; // Expression-bodied property | |
| private float _currentHealth = 100f; // private field for IKillable implementation | |
| // EVENTS / DELEGATES | |
| /// <summary> | |
| /// Event triggered before the game starts. | |
| /// </summary> | |
| public event Action GameStarting; // Name with a verb phrase, present participle | |
| /// <summary> | |
| /// Event triggered after the game has started. | |
| /// </summary> | |
| public event Action GameStarted; // Name with a verb phrase, past participle | |
| /// <summary> | |
| /// Event triggered when an enemy is spawned, includes the enemy count. | |
| /// </summary> | |
| public event Action<int> EnemySpawned; // Using System.Action delegate | |
| // MONOBEHAVIOUR METHODS | |
| private void Awake() | |
| { | |
| // Initialization code | |
| _currentEnemyCount = 0; | |
| _timeSinceLastSpawn = 0f; | |
| } | |
| private void Start() | |
| { | |
| // Good use of var when type is obvious | |
| var enemyList = new List<GameObject>(); | |
| var settings = new Dictionary<string, float>(); | |
| // AVOID: potential ambiguity with var | |
| // var currentSettings = GetGameSettings(); // Assuming GetGameSettings() returns a complex or not immediately obvious type | |
| StartGame(); | |
| } | |
| private void OnEnable() | |
| { | |
| // Example: Subscribing to an external event (if GameEvents class existed) | |
| // Assuming _gameEvents is an instance of a class like GameEvents from the style guide | |
| // _gameEvents.DoorOpened += GameEvents_DoorOpened; | |
| } | |
| private void OnDisable() | |
| { | |
| // Example: Unsubscribing from an external event | |
| // _gameEvents.DoorOpened -= GameEvents_DoorOpened; | |
| } | |
| private void Update() | |
| { | |
| if (!_isGameActive || !_canSpawnEnemies) return; | |
| _timeSinceLastSpawn += Time.deltaTime; | |
| if (_timeSinceLastSpawn >= _spawnInterval && _currentEnemyCount < _maxEnemies) | |
| { | |
| SpawnEnemy(); | |
| _timeSinceLastSpawn = 0f; | |
| } | |
| } | |
| // PUBLIC METHODS | |
| /// <summary> | |
| /// Starts the game. | |
| /// </summary> | |
| public void StartGame() // Starts with a verb | |
| { | |
| if (_isGameActive) return; | |
| OnGameStarting(); // Prefix event raising method with "On" | |
| _isGameActive = true; | |
| Debug.Log("Game Started!"); | |
| OnGameStarted(); // Prefix event raising method with "On" | |
| } | |
| /// <summary> | |
| /// Ends the game. | |
| /// </summary> | |
| public void EndGame() // Starts with a verb | |
| { | |
| _isGameActive = false; | |
| Debug.Log("Game Over!"); | |
| // Potentially raise a GameOver event here | |
| } | |
| /// <summary> | |
| /// Checks if the maximum number of enemies has been reached. | |
| /// </summary> | |
| /// <returns>True if max enemies reached, false otherwise.</returns> | |
| public bool HasMaxEnemies() // Method returning bool asks a question | |
| { | |
| return _currentEnemyCount >= _maxEnemies; | |
| } | |
| /// <summary> | |
| /// Inflicts damage on the GameManager (as an IKillable entity). | |
| /// </summary> | |
| /// <param name="damageAmount">The amount of damage to inflict.</param> | |
| public void InflictDamage(float damageAmount, bool isCriticalHit) // Parameters are camel case | |
| { | |
| // Local variable, noun | |
| float totalDamage = damageAmount; | |
| if (isCriticalHit) // isCriticalHit is a boolean parameter, prefixed with a verb | |
| { | |
| totalDamage *= 2.0f; // Using a magic number, consider making it a const or field | |
| } | |
| _currentHealth -= totalDamage; | |
| Debug.Log($"GameManager took {totalDamage} damage. Current health: {_currentHealth}"); | |
| if (IsDead) | |
| { | |
| Kill(); | |
| } | |
| } | |
| // IKillable implementation | |
| public void Kill() // Starts with a verb | |
| { | |
| if (IsDead) | |
| { | |
| Debug.Log("GameManager has been 'killed' (e.g., core destroyed)."); | |
| EndGame(); | |
| } | |
| } | |
| // PRIVATE METHODS | |
| /// <summary> | |
| /// Spawns a new enemy. | |
| /// </summary> | |
| private void SpawnEnemy() // Starts with a verb | |
| { | |
| _currentEnemyCount++; | |
| Debug.Log($"Enemy spawned. Total enemies: {_currentEnemyCount}"); | |
| OnEnemySpawned(_currentEnemyCount); // Prefix event raising method with "On" | |
| } | |
| /// <summary> | |
| /// Raises the GameStarting event. | |
| /// </summary> | |
| private void OnGameStarting() // Prefix with "On" for event raising method | |
| { | |
| GameStarting?.Invoke(); // Using System.Action | |
| } | |
| /// <summary> | |
| /// Raises the GameStarted event. | |
| /// </summary> | |
| private void OnGameStarted() // Prefix with "On" for event raising method | |
| { | |
| GameStarted?.Invoke(); | |
| } | |
| /// <summary> | |
| /// Raises the EnemySpawned event. | |
| /// </summary> | |
| /// <param name="enemyCount">The current count of enemies.</param> | |
| private void OnEnemySpawned(int enemyCount) // Prefix with "On" for event raising method | |
| { | |
| EnemySpawned?.Invoke(enemyCount); // Using System.Action<T> | |
| } | |
| // Example of an event handler method (if GameEvents class existed and we were observing it) | |
| // /// <summary> | |
| // /// Handles the DoorOpened event from GameEvents. | |
| // /// </summary> | |
| // private void GameEvents_DoorOpened() // Prefix with subject's name and underscore | |
| // { | |
| // Debug.Log("Notification received: A door was opened!"); | |
| // } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using UnityEngine; | |
| // Example: Enum conventions | |
| // Use PascalCase for enum names and values, place public enums outside the class, and use a singular noun for the enum name. | |
| public enum PlayerState | |
| { | |
| Idle, | |
| Running, | |
| Jumping, | |
| Dead | |
| } | |
| // Example: Interface conventions | |
| // Use PascalCase for interface names, prefix with 'I' and use an adjective describing the functionality | |
| public interface IDamageable | |
| { | |
| void TakeDamage(int amount); | |
| } | |
| // Example: Class conventions | |
| // Use PascalCase nouns for class names, ensure MonoBehaviour filename matches and only one per file | |
| public class UnityStyleGuideExample : MonoBehaviour | |
| { | |
| //==================== Fields ==================== | |
| // Use nouns for variable names | |
| [SerializeField] private int _playerScore; | |
| [SerializeField] private float _movementSpeed; | |
| // Prefix booleans with a verb | |
| [SerializeField] private bool _isJumping; | |
| [SerializeField] private bool _hasPowerUp; | |
| // Use meaningful names. Don’t abbreviate (unless it’s math) | |
| [SerializeField] private string _playerName; | |
| [SerializeField] private int _numberOfLives; | |
| // Use PascalCase for public fields | |
| public int MaxHealth; | |
| public float JumpHeight; | |
| // Use camelCase with _ prefix for private fields | |
| private int _currentHealth; | |
| private float _jumpCooldown; | |
| // Prefer [SerializeField] over public for Inspector exposure | |
| [SerializeField] private int _coinsCollected; | |
| [SerializeField] private bool _canDoubleJump; | |
| private int _experiencePoints; | |
| //==================== Properties ==================== | |
| // Example: Properties conventions | |
| // Use expression-bodied property for single line read-only property | |
| public int PlayerScore => _playerScore; | |
| // Use auto-implemented property for read/write | |
| public int Level { get; set; } | |
| // Multi-line property with custom logic, braces aligned | |
| public int ExperiencePoints | |
| { | |
| get { return _experiencePoints; } | |
| set | |
| { | |
| if (value >= 0) | |
| _experiencePoints = value; | |
| } | |
| } | |
| //==================== Events / Delegates ==================== | |
| // Example: Events and event handlers conventions | |
| // Name the event with a verb phrase, use System.Action, and prefix raiser with 'On' | |
| public event System.Action DoorOpened; | |
| public event System.Action<int> PlayerScored; | |
| //==================== Monobehaviour Methods ==================== | |
| // (Add Unity lifecycle methods here as needed) | |
| //==================== Public Methods ==================== | |
| // Use camelCase for local variables | |
| public void UpdatePlayerScore(int score) | |
| { | |
| int newScore = _playerScore + score; | |
| _playerScore = newScore; | |
| } | |
| // Example: Methods conventions | |
| // Start method names with a verb and add context if necessary | |
| public Vector3 GetDirection(Vector3 targetPosition) | |
| { | |
| return (targetPosition - transform.position).normalized; | |
| } | |
| public void FindTarget(string targetTag) | |
| { | |
| GameObject target = GameObject.FindWithTag(targetTag); | |
| // ...additional logic... | |
| } | |
| // Use camelCase for parameters | |
| public void MovePlayer(float moveSpeed) | |
| { | |
| transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime); | |
| } | |
| // Methods returning bool should ask questions and be prefixed with a verb | |
| public bool IsGameOver() | |
| { | |
| return _currentHealth <= 0; | |
| } | |
| public bool HasStartedTurn() | |
| { | |
| return _numberOfLives > 0 && _playerScore > 0; | |
| } | |
| // Method to raise the event, prefixed with 'On' | |
| protected virtual void OnDoorOpened() | |
| { | |
| DoorOpened?.Invoke(); | |
| } | |
| protected virtual void OnPlayerScored(int score) | |
| { | |
| PlayerScored?.Invoke(score); | |
| } | |
| // Example observer/handler method, prefixed with subject name and underscore | |
| public void UnityStyleGuideExample_DoorOpened() | |
| { | |
| // Handle door opened event | |
| } | |
| public void UnityStyleGuideExample_PlayerScored(int score) | |
| { | |
| // Handle player scored event | |
| } | |
| //==================== Private Methods ==================== | |
| // (Add private helper methods here) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment