Unity Tutorial: Learn Game Development from Scratch (2026)
Unity is the most widely used game engine for indie and mobile games, powering everything from Among Us to Genshin Impact. After releasing two mobile games and building a VR training simulation with Unity, I have found its biggest strength to be the asset pipeline — you can go from Blender model to playable prototype faster than any other engine.
This tutorial covers the Unity editor, C# scripting, physics, animation, UI, and optimization. You will build a complete 2D platformer from scratch, learning the patterns that professional Unity developers use daily.
Editor and Scene Hierarchy
The Unity editor organizes games into Scenes (levels), GameObjects (everything in the scene), and Components (behaviors attached to objects). A GameObject is an empty container; it becomes visible with a MeshRenderer, physical with a Rigidbody, and interactive with a Collider and script. This component-based architecture is the core pattern in Unity.
The hierarchy window shows the parent-child tree of objects. The Inspector shows all components on the selected object and allows real-time editing. Press Play to enter Play Mode and test your game without building.
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float moveSpeed = 5f;
public float jumpForce = 10f;
private Rigidbody2D rb;
private bool isGrounded;
void Start()
{
rb = GetComponent();
}
void Update()
{
float move = Input.GetAxisRaw("Horizontal");
rb.linearVelocity = new Vector2(move * moveSpeed, rb.linearVelocity.y);
if (Input.GetButtonDown("Jump") && isGrounded)
{
rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
}
}
}
C# Scripting Lifecycle
Every Unity script extends MonoBehaviour, with lifecycle methods: Awake() (on load), Start() (before first frame), Update() (every frame), FixedUpdate() (fixed timestep for physics), and OnCollisionEnter2D() (collision events). Use Time.deltaTime to make movement frame-rate independent.
Use Input.GetAxis for smooth input. Cache GetComponent() references in Start(). Coroutines (IEnumerator) handle delays without blocking the main thread.
public class Enemy : MonoBehaviour
{
public float speed = 2f;
private Transform target;
void Start()
{
target = GameObject.FindGameObjectWithTag("Player").transform;
}
void Update()
{
float step = speed * Time.deltaTime;
transform.position = Vector3.MoveTowards(
transform.position, target.position, step
);
}
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Player"))
{
Destroy(collision.gameObject);
}
}
}
Physics System
Unity's physics engine (Box2D for 2D, PhysX for 3D) handles collision detection and rigid body dynamics. A Rigidbody2D makes an object subject to physics. Colliders define the collision shape. IsTrigger detects overlaps without physical collision response.
Layers and Layer Collision Matrix control which objects interact. Use Physics2D.Raycast for line-of-sight checks — much cheaper than collider-based detection.
public class GroundCheck : MonoBehaviour
{
public LayerMask groundLayer;
public float checkRadius = 0.2f;
public bool IsGrounded()
{
Collider2D hit = Physics2D.OverlapCircle(
transform.position, checkRadius, groundLayer
);
return hit != null;
}
void OnDrawGizmos()
{
Gizmos.color = IsGrounded() ? Color.green : Color.red;
Gizmos.DrawWireSphere(transform.position, checkRadius);
}
}
Animation State Machines
Unity's Animator uses a state machine with parameters (float, int, bool, trigger) that control transitions between animation states. Create animations from keyframed properties or import from Blender/Maya. The Animator Controller shows states as boxes and transitions as arrows.
Blend Trees blend between multiple animations based on a parameter. Use Animation Events to call functions at specific frames. For 2D, sprite sheet slicing enables frame-by-frame animation from a single texture atlas.
public class PlayerAnimation : MonoBehaviour
{
private Animator animator;
private SpriteRenderer sprite;
void Start()
{
animator = GetComponent();
sprite = GetComponent();
}
void Update()
{
float speed = Mathf.Abs(rb.linearVelocity.x);
animator.SetFloat("Speed", speed);
animator.SetBool("IsGrounded", isGrounded);
if (rb.linearVelocity.x > 0.1f) sprite.flipX = false;
else if (rb.linearVelocity.x < -0.1f) sprite.flipX = true;
}
}
UI Toolkit and Canvas
Unity's UI system uses a Canvas (render space), RectTransform (UI positioning), and UI components (Text, Image, Button, Slider). The Canvas can be in Screen Space (overlay, camera, or world space). Use Canvas Scaler for resolution-independent scaling.
Buttons have an onClick event wired to methods in the Inspector or dynamically in scripts. Layout Groups automatically arrange child elements for complex layouts.
public class UIManager : MonoBehaviour
{
public Text scoreText;
public GameObject gameOverPanel;
public Button restartButton;
void Start()
{
restartButton.onClick.AddListener(RestartGame);
gameOverPanel.SetActive(false);
}
public void UpdateScore(int score)
{
scoreText.text = $"Score: {score}";
}
public void ShowGameOver()
{
gameOverPanel.SetActive(true);
Time.timeScale = 0f;
}
void RestartGame()
{
Time.timeScale = 1f;
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
}
Mobile Optimization
Mobile games dominate Unity's market. Key optimizations: use sprite atlases to reduce draw calls, limit transparent objects (overdraw), use object pooling instead of Instantiate/Destroy, and profile with the Unity Profiler early.
For builds: File > Build Settings > switch platform to Android/iOS. Use IL2CPP for better performance. Always test on a real device before release.
public class BulletPool : MonoBehaviour
{
public GameObject bulletPrefab;
public int poolSize = 20;
private Queue pool = new Queue();
void Start()
{
for (int i = 0; i < poolSize; i++)
{
GameObject obj = Instantiate(bulletPrefab);
obj.SetActive(false);
pool.Enqueue(obj);
}
}
public GameObject GetBullet()
{
if (pool.Count == 0) return null;
GameObject obj = pool.Dequeue();
obj.SetActive(true);
return obj;
}
public void ReturnBullet(GameObject obj)
{
obj.SetActive(false);
pool.Enqueue(obj);
}
}
Frequently Asked Questions
Do I need to know C# before starting Unity?
Basic C# syntax is helpful but not mandatory. Unity's scripting API is well-documented with hundreds of examples. Start with the Unity Learn platform's 'Create with Code' course.
Should I use 2D or 3D for my first game?
2D is significantly simpler. No lighting, no complex physics, no camera management. With the same time investment, you can have a playable 2D platformer in one week versus a basic 3D scene with a character controller.
How do I handle saving game progress?
Use PlayerPrefs for simple data. For complex game state, serialize objects to JSON and write to Application.persistentDataPath. For cloud saves, use Unity Cloud Save or a backend service.
What is the best way to handle multiplayer in Unity?
Unity Netcode for GameObjects (NGO) is the official solution for small-to-medium multiplayer games. For large-scale MMOs, use Photon, Mirror, or Fish-Net. For turn-based games, use Unity Gaming Services Relay + Lobby.
Originally published on Ayodhyyya. Last updated June 1, 2026.