Skip to content
Unity Game Development with C#: Complete Beginner's Guide

Unity Game Development with C#: Complete Beginner's Guide

DodaTech Updated Jun 20, 2026 6 min read

Unity combines a visual editor with C# scripting to let you build 2D, 3D, VR, and AR games for 25+ platforms. C# is the language that brings your GameObjects to life — without it, you have a static scene.

In this tutorial, you’ll learn Unity’s C# scripting model: MonoBehaviour lifecycle, physics with Rigidbody and Collider, input handling, prefabs, scenes, and build settings. By the end, you’ll have a working player controller and understand how to structure a Unity project.

What You’ll Learn

  • Unity interface: Scene, Game, Hierarchy, Project, Inspector panels
  • GameObjects and components architecture
  • MonoBehaviour lifecycle: Awake, Start, Update, FixedUpdate, LateUpdate
  • Physics: Rigidbody, Collider, triggers, raycasts
  • Input handling with InputManager and InputSystem
  • Prefabs, scenes, and build settings

Why Unity C# Matters

Unity powers games like Hollow Knight, Cities: Skylines, and Among Us. Beyond games, it’s used in architecture visualization, film production, and training simulations. C# in Unity is approachable for beginners and powerful enough for AAA studios. At DodaTech, we use Unity for interactive product demos in Doda Browser that showcase hardware acceleration across devices.

Learning Path

    flowchart LR
  A[Game Dev Overview] --> B[Unity Guide]
  B --> C[Unity C# Scripting<br/>You are here]
  C --> D[Unreal Blueprints]
  C --> E[2D Animation]
  style C fill:#f90,color:#fff
  

The Unity Interface

Unity’s editor has five key panels:

PanelPurpose
SceneVisual viewport for editing your game world
GameRenders what the camera sees — your play view
HierarchyLists every GameObject in the current scene
ProjectFile browser for assets, scripts, and scenes
InspectorShows properties of the selected GameObject or asset

A GameObject is every object in your scene — a character, camera, light, or empty marker. It’s an invisible container that holds components (scripts, renderers, colliders, audio sources). Components give GameObjects their behavior and appearance.

MonoBehaviour and the Lifecycle

Every C# script that needs to run in a scene extends MonoBehaviour. This base class gives you lifecycle methods that Unity calls automatically:

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    void Awake()
    {
        // Called when the script instance is loaded (before Start)
        Debug.Log("Player is waking up");
    }

    void Start()
    {
        // Called before the first frame update (after Awake)
        Debug.Log("Player is starting");
    }

    void Update()
    {
        // Called once per frame (frame-rate dependent)
        // Use for input reading, non-physics movement, timers
    }

    void FixedUpdate()
    {
        // Called at a fixed timestep (default 0.02s)
        // Use for physics calculations (Rigidbody forces, movement)
    }

    void LateUpdate()
    {
        // Called after all Update methods
        // Use for camera follow, IK adjustments
    }
}

Expected output: The console prints “Player is waking up”, then “Player is starting” on scene load.

Physics: Rigidbody and Collider

Physics in Unity requires two components:

  1. Rigidbody — enables physics simulation (gravity, forces, velocity)
  2. Collider — defines the shape used for collision detection (Box, Sphere, Capsule, Mesh)
using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
    public float speed = 5f;
    public float jumpForce = 7f;
    private Rigidbody rb;
    private bool isGrounded;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void Update()
    {
        // Read input in Update (frame-rate independent input read)
        float moveX = Input.GetAxis("Horizontal");
        float moveZ = Input.GetAxis("Vertical");
        Vector3 move = transform.right * moveX + transform.forward * moveZ;

        // Apply physics movement in FixedUpdate
        if (Input.GetButtonDown("Jump") && isGrounded)
        {
            rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
            isGrounded = false;
        }

        // Use MovePosition for smooth physics-based movement
        rb.MovePosition(transform.position + move * speed * Time.deltaTime);
    }

    void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.CompareTag("Ground"))
            isGrounded = true;
    }

    void OnCollisionExit(Collision collision)
    {
        if (collision.gameObject.CompareTag("Ground"))
            isGrounded = false;
    }
}

Expected behavior: Press WASD to move, Space to jump. The player can only jump when touching the ground. Time.deltaTime makes movement frame-rate independent.

Working with Prefabs

A prefab is a reusable GameObject template. Create an enemy once, save it as a prefab, and instantiate it at runtime:

public class BulletSpawner : MonoBehaviour
{
    public GameObject bulletPrefab;
    public Transform firePoint;

    void Update()
    {
        if (Input.GetButtonDown("Fire1"))
        {
            GameObject bullet = Instantiate(
                bulletPrefab,
                firePoint.position,
                firePoint.rotation
            );
            // Destroy bullet after 2 seconds to avoid memory leaks
            Destroy(bullet, 2f);
        }
    }
}

Expected behavior: Clicking the mouse (or pressing Ctrl) spawns a bullet prefab at the fire point. The bullet self-destructs after 2 seconds.

Changes to the prefab asset update every instance — the same approach used in DodaZIP for template-based file generation.

Scenes and Build Settings

A scene is a container for your game world. Games typically have multiple scenes:

MenuScene → GameScene → GameOverScene

Switch scenes programmatically:

using UnityEngine.SceneManagement;

public class SceneSwitcher : MonoBehaviour
{
    public void LoadGameScene()
    {
        SceneManager.LoadScene("GameScene");
    }

    public void ReloadCurrentScene()
    {
        Scene currentScene = SceneManager.GetActiveScene();
        SceneManager.LoadScene(currentScene.name);
    }
}

Build Settings (File > Build Settings) let you:

  • Add all scenes to the build list
  • Set the platform target (Windows, Mac, Linux, Android, iOS, WebGL)
  • Configure player settings (resolution, icon, company name)

Common Mistakes Beginners Make

1. Modifying transform.position on a Rigidbody

Use rb.MovePosition() or rb.AddForce() instead. Direct position changes bypass physics and cause jittery, unrealistic movement.

2. Forgetting Time.deltaTime

Movement without Time.deltaTime runs at different speeds on different frame rates. Always multiply movement by Time.deltaTime for consistency.

3. Checking Input in FixedUpdate

Input.GetAxis() reads correctly in Update(). In FixedUpdate(), input values may be stale. Read input in Update() and apply physics in FixedUpdate().

4. Scaling the Parent Instead of Children

Non-uniform scaling on a parent object distorts child colliders. Keep root objects at (1,1,1) scale.

5. Not Using CompareTag

gameObject.tag == "Enemy" allocates memory. Use gameObject.CompareTag("Enemy") — it’s faster and zero-alloc.

6. Attaching Scripts to Wrong Objects

A movement script on the camera won’t move the player. Attach scripts to the GameObject they control.

7. Forgetting Layer Collision Matrix

Configure Edit > Project Settings > Physics > Layer Collision Matrix to prevent, say, player bullets hitting the player who fired them.

Practice Questions

1. What’s the difference between Update() and FixedUpdate()?

Update() runs every frame (variable rate). FixedUpdate() runs at a fixed timestep (default 0.02s) and is used for physics calculations.

2. Why use Instantiate() with prefabs?

Prefabs allow you to spawn objects at runtime without having copies sitting in the scene. Changes to the prefab propagate to all instances.

3. What does Time.deltaTime do?

It returns the time in seconds since the last frame. Multiplying movement by it makes speed independent of frame rate.

4. How do you detect a collision in Unity?

Add OnCollisionEnter(Collision collision) to a script on a GameObject that has both a Collider and a Rigidbody.

5. Challenge: Add a sprint mechanic with stamina.

Track isSprinting bool. When LeftShift is held, multiply speed by 2. Add a stamina float that depletes while sprinting and recovers at rest. Clamp it between 0 and maxStamina.

Mini Project: Ball Collector

Create a new 3D project:

  1. Add a Sphere with Rigidbody and SphereCollider
  2. Write a script that applies force based on arrow keys
  3. Create Cube pickups with BoxCollider (isTrigger = true)
  4. Add OnTriggerEnter to detect pickups, destroy them, increment score
  5. Display score with TextMeshPro

FAQ

Does Unity cost money?
Unity Personal is free for individuals and studios with under $200K annual revenue. Unity Pro ($2,040/year) adds the Profiler, cloud build, and more.
What language does Unity use?
C# is the primary scripting language. Unity also supports Visual Scripting (node-based) for non-programmers.
Can Unity make 2D games?
Yes. Unity has dedicated 2D tools: sprite renderer, tilemap system, 2D physics (Box2D), and sprite shape tools.

What’s Next

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro