C# SCRIPTING FOR UNITY GAME DEVELOPERS HUB

A developer-crafted learning curriculum for writing clean, performant, and decoupled C# code inside Unity's component ecosystem.

Writing Idiomatic C# for Unity

Writing C# for Unity differs substantially from general software engineering. In Unity, performance is tied directly to the MonoBehaviour lifecycle (Awake, Start, Update, FixedUpdate, LateUpdate), Garbage Collection (GC) pressure, and avoiding costly interop calls across the native C++ engine boundary.

Component Caching
Calling GetComponent<T>() inside Update() queries the native engine hierarchy each frame. Cache component references in Awake() to preserve CPU cycles.
Event-Driven Decoupling
Replace hard spaghetti references with C# System.Action delegates. When a player takes damage, fire an OnPlayerDamaged event rather than manually updating UI scripts.
Garbage-Free Scripting
Avoid string concatenations ("Score: " + score), LINQ allocations, and new List<T>() instances inside frame loops to eliminate GC hitching on Android.

Guides in This Cluster

Understand [SerializeField] vs public, value types (float, int, bool, Vector3) vs reference types, variable shadowing, and scope boundaries.

How to write modular methods, pass arguments by value vs reference (ref/out), default parameters, and clean method organization.

Learn why GetComponent is slow in loops, how to cache references in Awake(), use TryGetComponent safely, and leverage [RequireComponent].

Compare Direct Referencing, Singleton Patterns, C# Events/Delegates, and ScriptableObject architecture to build scalable game systems without tightly coupled code.

Understand the execution order of Unity's event functions, when to process player input, when to calculate physics, and how to eliminate camera stutter.

Why games run faster on 144Hz monitors if Time.deltaTime is missing, how to scale movement and timers accurately, and how Time.timeScale works for slow motion.

Developer Tools & C# Error Troubleshooting

🛠️ C# Developer Tools

C# Scripting FAQ

Using public exposes variables to every other script in the project, breaking encapsulation and making it easy for unrelated scripts to corrupt state. Using [SerializeField] private float speed; exposes the variable in the Unity Inspector for designers while keeping the variable safely protected from other scripts.
Awake() executes immediately when the prefab/GameObject is instantiated, even if the script component is disabled. Use Awake() for internal self-initialization (like GetComponent). Start() executes right before the first frame update, only if the script is enabled. Use Start() for inter-object setup when all other objects have finished their Awake().