Guide
Unity fundamentals explained
You drag a sprite into the Hierarchy, attach a Rigidbody2D, write a
dozen lines of C# in PlayerController.cs, and press Play. The character
jumps, collides with platforms, and triggers a coin pickup sound. That workflow is
Unity Engine in miniature — a cross-platform game engine where
everything in a scene is a GameObject and behavior arrives through
attachable components. Unity 6 (2023 LTS line and beyond) ships
the Universal Render Pipeline (URP), the modern Input System, 2D and 3D physics,
UI Toolkit alongside legacy uGUI, and one-click builds for mobile, desktop, console,
and WebGL. It powers mobile hits, indie darlings, and AAA-adjacent titles alike.
This guide covers the component model, C# scripting and lifecycle, prefabs and scenes,
input, physics, UI, ScriptableObjects, packages and rendering, a Harbor Arcade
coin-collector worked example, an engine decision table, common pitfalls, and a
practitioner checklist — alongside our
Godot fundamentals guide
and
game loop guide.
What Unity is (and how it differs from Godot or Unreal)
Unity is a general-purpose real-time engine maintained by Unity
Technologies. Unlike
Godot’s scene-tree
of typed nodes or Unreal’s Actor hierarchy with Blueprints, Unity uses an
entity-component pattern: empty GameObjects gain capabilities by
stacking components (Transform, SpriteRenderer,
BoxCollider2D, custom scripts). Composition beats deep inheritance
— reuse a “Enemy” prefab by swapping scripts and tuning inspector
fields rather than subclassing engine types.
Unity’s primary scripting language is C# compiled against .NET Standard / .NET Framework profiles depending on version. The editor runs on Windows, macOS, and Linux. Licensing shifted in 2024: a free Personal tier covers most indies under revenue thresholds; Pro and Enterprise add analytics, support, and compliance tooling. Unity’s asset store, mobile ad SDK ecosystem, and console export pipelines remain reasons teams pick it over open-source alternatives when time-to-store matters.
Core subsystems at a glance
- GameObjects and components — scene hierarchy; add/remove behavior without subclassing engine classes.
- C# scripting —
MonoBehaviourlifecycle hooks; coroutines; async/await in newer runtimes. - Prefabs — reusable, versioned object templates; prefab variants for incremental overrides.
- Rendering — Built-in (legacy), URP (mobile/PC default), HDRP (high-end); Scriptable Render Pipeline architecture.
- Physics — 3D PhysX and 2D Box2D wrappers;
Rigidbody,CharacterController, trigger colliders. - Input — new Input System (action maps, rebinding) vs legacy
Input.GetAxis. - UI — uGUI (Canvas-based) and UI Toolkit (USS/UXML, growing for editor and runtime).
- Package Manager — modular features (Cinemachine, Addressables, Netcode) installed per project.
GameObjects, components, and the scene hierarchy
Every object in a level is a GameObject. At minimum it carries a
Transform (position, rotation, scale). Rendering needs a
MeshRenderer or SpriteRenderer; collision needs
Collider shapes; audio needs AudioSource. Custom
MonoBehaviour scripts appear as components too, exposing public fields
the Inspector serializes into YAML scene files.
Parent-child relationships inherit transforms: a weapon model parented to a hand bone moves with the character rig. Tags and Layers classify objects for physics matrix filtering and raycasts — mirror the collision-layer discipline described in our game physics guide. Empty GameObjects often act as anchors (spawn points, camera rigs, audio listeners).
Scenes and build order
A scene is a self-contained level or menu stored as a
.unity file. The Build Settings list defines load
order; index 0 is the boot scene. Use SceneManager.LoadScene for
full swaps or additive loading for open worlds. Keep scenes small enough for fast
iteration — large projects split environments into additive addressable
chunks.
C# scripting and the MonoBehaviour lifecycle
Scripts inherit MonoBehaviour and attach to GameObjects. Unity calls
lifecycle methods in a defined order each frame:
Awake— object constructed; cache component references here.OnEnable/OnDisable— object toggled active; subscribe/unsubscribe to events.Start— first frame before Update if enabled; safe for cross-object lookups.Update/FixedUpdate/LateUpdate— frame logic, physics, camera follow.OnCollisionEnter/OnTriggerEnter— physics callbacks.OnDestroy— cleanup when object removed.
Apply forces and read physics state in FixedUpdate (fixed timestep),
not Update, to stay aligned with the physics engine — the same
rule as Godot’s _physics_process. Use
Time.deltaTime in Update for frame-rate-independent motion.
Coroutines (StartCoroutine) yield across frames for
delays and sequences without async complexity; prefer C# async only
where supported and understood (WebGL has constraints).
Serialization and inspector-driven design
Public fields and [SerializeField] private fields appear in the
Inspector, letting designers tune speeds and references without recompiling.
[Header], [Tooltip], and [Range] attributes
document tuning knobs. Avoid heavy logic in property getters that run every Inspector
repaint in edit mode.
Prefabs, ScriptableObjects, and data-driven design
Prefabs store GameObject hierarchies as reusable assets. Editing a
prefab propagates to all instances unless overridden. Prefab variants
inherit from a base enemy and override only health or mesh — cleaner than
duplicating whole prefabs. Instantiate at runtime with
Instantiate(enemyPrefab, spawnPoint.position, spawnPoint.rotation).
ScriptableObjects are data assets (not scene objects) ideal for
item definitions, wave tables, dialogue lines, and audio clip maps. They load once,
survive scene changes, and diff cleanly in version control compared to giant
MonoBehaviour lists on scene objects. Pattern: a CoinDefinition
ScriptableObject holds sprite, value, and pickup sound; pickup scripts reference
the asset.
Input, physics, and UI
Input System
Install the Input System package and define an
InputActionAsset with action maps (Move, Jump, Fire). Bind keyboard,
gamepad, and touch in one place; enable rebinding UI for accessibility. Read values
via playerInput.actions["Move"].ReadValue<Vector2>()
or generated C# wrapper classes. Disable legacy input when migrating to avoid double
reads.
2D and 3D physics
2D games use Rigidbody2D with Collider2D shapes;
platformers often set bodyType to Dynamic with constrained rotation.
Use Physics2D layer collision matrix to ignore player-player
contact. 3D projects use CharacterController for kinematic walkers or
Rigidbody for physics-driven motion. Triggers (isTrigger)
detect overlap without solid collision — standard for pickups and zones.
User interface
uGUI places Canvas elements (Text, Image, Button) in screen space.
Wire button onClick to public methods. Scale with Canvas Scaler
(reference resolution + match width/height). UI Toolkit uses
UXML layout and USS stylesheets — closer to web CSS, better for complex menus
and editor tools. Pick one stack per project screen to avoid event-system conflicts.
Packages, rendering, and build pipeline
Unity modularizes features through the Package Manager: Cinemachine for cameras, Addressables for remote content, Netcode for GameObjects for multiplayer prototypes. Choose a render pipeline at project creation: URP balances mobile and PC; HDRP targets high-fidelity PC/console. Pipeline assets control lighting, shadows, and post- processing globally.
Build Profiles (Unity 6) consolidate platform settings: texture compression (ASTC on mobile), scripting backend (IL2CPP for iOS/consoles), managed stripping levels, and keystore references. IL2CPP improves performance and obscures C# but lengthens build times — budget CI accordingly. Test device builds early; shader variants and overdraw show up only on real GPUs.
Worked example: Harbor Arcade coin collector (Unity 6, 2D URP)
Harbor Arcade needs a mobile-friendly mini-game: the player moves a character, collects ten coins, and unlocks an exit door. Scope fits one week in Unity 6 with 2D URP and Android export.
- Project setup — 2D URP template, orthographic camera sized for 16:9 reference (1920×1080), pixel-perfect camera optional for crisp art.
- Player prefab —
SpriteRenderer+Rigidbody2D(Dynamic, freeze rotation Z) +CapsuleCollider2D.PlayerControllerreads Input System Move vector, setsrb.velocityin FixedUpdate, flips sprite on X. - Coin prefab — trigger
CircleCollider2D;CoinPickupscript referencesCoinDefinitionScriptableObject; on trigger, callsGameManager.AddScore(value)and plays one-shot audio. - Level scene — Tilemap palette for ground; placed coin instances;
ExitDoortrigger checksGameManager.Score >= 10before enabling animator “Open” state. - GameManager singleton — DontDestroyOnLoad optional; raises
OnScoreChangedevent; persists best score withPlayerPrefs. - HUD — uGUI Text bound to score event; no polling in Update.
- Build — Android IL2CPP, ARM64 only, minimum API 24; test on mid-tier device for thermal throttling during sustained play.
Design choices mirror our platformer design guide: early coins sit on flat ground; later coins require a jump gap once the move feel is learned. Coyote time implemented as a 0.12s grace timer after leaving ground contact.
Engine decision table
| Need | Prefer Unity | Consider alternative |
|---|---|---|
| Mobile F2P with ads, IAP, analytics SDKs | Unity — mature store integrations and profiling tools | Godot (lighter, fewer native SDKs) |
| 2D indie game, zero license cost, MIT-style freedom | Unity Personal may suffice under revenue caps | Godot 4 — no royalties, smaller export size |
| High-end 3D, photoreal console title | Unity HDRP can work for mid-tier AAA | Unreal Engine 5 — Nanite, MetaHuman, console-first defaults |
| Browser-first HTML5 arcade | Unity WebGL (large download, WASM) | Phaser, Godot web export, or custom canvas |
| Team deep in C# and Visual Studio | Unity — first-class C# debugging | Godot C# branch if open source is mandatory |
| Procedural roguelike with rapid content iteration | Either engine; Unity Addressables help asset streaming | Match team skill — see roguelike design guide |
Common pitfalls
- Physics in Update instead of FixedUpdate — causes jitter and frame-rate-dependent jump height.
- GetComponent every frame — cache references in Awake/Start;
GetComponentis relatively expensive. - Instantiate without pooling — bullet-hell and mobile projects GC-stutter; reuse with object pools.
- Ignoring script execution order — race conditions when Manager Start runs after dependent objects; set order or use Awake.
- Massive unoptimized WebGL builds — strip unused engine modules, compress textures, test on throttled networks.
- Singleton abuse — global statics hide dependencies; prefer explicit references or lightweight service locators.
Production checklist
- Pin Unity editor version in README; commit
ProjectSettings/ProjectVersion.txt. - Input action maps documented; keyboard, gamepad, and touch tested on target hardware.
- Physics layer matrix written down; debug gizmos verified on representative levels.
- Profiler pass on lowest-spec target device; eliminate Update scripts over 1 ms.
- Addressables or asset bundles planned if build size exceeds store limits.
- IL2CPP build tested before milestone locks; allow extra CI time for linking.
- Store metadata (icons, privacy policy URL, age rating) prepared before submission.
- Crash analytics (Backtrace, Unity Cloud Diagnostics) wired before soft launch.
Key takeaways
- GameObjects + components are Unity’s core abstraction — compose behavior instead of deep inheritance trees.
- C# MonoBehaviour lifecycle separates initialization, frame logic, and physics; respect FixedUpdate for forces.
- Prefabs and ScriptableObjects keep scenes lean and data designer-friendly.
- URP + Input System + Package Manager form the modern Unity stack; choose pipeline early.
- Engine proficiency does not replace design — pair Unity skills with pacing, juice, and clear goals from our game design guides.
Related reading
- Godot fundamentals explained — open-source scene-tree alternative
- Game loop and frame timing explained — Update vs FixedUpdate theory
- Platformer game design explained — coyote time, level teaching, movement feel
- Game physics explained — rigid bodies, triggers, and integration