Skip to content

Expert · Testing, tooling and Unity · topic 39 of 43 · 35 min

Game development with Unity and C#

Explanation

Unity is a widely used game engine, and its scripts are written in C#. A scene contains GameObjects; each GameObject is built from components such as Transform, Rigidbody, Collider and your own scripts. A script is a class that inherits from MonoBehaviour: Start runs once, Update runs every frame, and FixedUpdate runs on each physics step. Multiply movement by Time.deltaTime so the game runs at the same speed on every device.

Why Unity?

Unity is used for a large share of mobile games, many PC and console games, and AR/VR apps, and also outside games: architecture walkthroughs, training simulators and car configurators. Indian studios and outsourcing companies hire Unity developers, and the C# you have learned carries straight over. Install it through Unity Hub from unity.com; the personal licence is free within Unity's revenue limits (check the current terms).

How Unity differs from the .NET you know

  • There is no Main method or Program.cs. The Unity engine owns the game loop and calls your methods at the right times.
  • Unity runs C# on its own scripting runtime, not the latest .NET, so not every new C# feature or .NET API is available. Check the Unity manual for the C# version your Unity version supports.
  • You attach scripts to objects in the Unity Editor, and public or [SerializeField] fields appear in the Inspector window so designers can tweak values without code.

GameObjects and components

Everything in a scene is a GameObject: the player, an enemy, a coin, the camera, a light. On its own a GameObject does nothing. Components give it abilities: Transform (position, rotation, scale; every object has one), a Renderer (to be seen), a Collider (a shape for collisions), a Rigidbody (to be moved by physics) and your scripts (behaviour). This is composition, not deep inheritance, which you met in module 5.

Think of it like this: A GameObject is like an empty thali plate. On its own it is just a plate. You add dal, rice, roti and sabzi (components) to make it a meal. Want a different meal? Change the items, not the plate.

Your first script

csharp
using UnityEngine;

public class PlayerMove : MonoBehaviour
{
    [SerializeField] private float speed = 5f;   // editable in the Inspector

    void Start()
    {
        Debug.Log("Player ready");                // prints to Unity's Console window
    }

    void Update()
    {
        float x = Input.GetAxis("Horizontal");    // -1 to 1 from arrow keys / A and D
        float z = Input.GetAxis("Vertical");
        Vector3 move = new Vector3(x, 0f, z) * speed * Time.deltaTime;
        transform.Translate(move);
    }
}
The file name must match the class name: PlayerMove.cs. Drag the script onto a GameObject to attach it.
Careful: Input.GetAxis belongs to the older Input Manager. New projects in recent Unity versions may use the newer Input System package instead, and then this call reports an error unless "Active Input Handling" in Player Settings includes the old system. The idea of reading input each frame is the same in both; follow the input approach your Unity version and tutorial use.

Time.deltaTime: speed that does not depend on the device

Update runs once per frame. A fast PC might draw 144 frames a second; an old phone might draw 30. If you move 0.1 units per frame, the object moves almost five times faster on the PC. Time.deltaTime is the time in seconds since the last frame, so speed * Time.deltaTime means "speed units per second" on every device.

The main lifecycle methods

MethodWhen Unity calls itUse it for
AwakeWhen the object is loaded, before StartGetting references to your own components
StartOnce, before the first frame the script is activeSetup that needs other objects
UpdateEvery frameInput, simple movement, timers
FixedUpdateEvery physics step (fixed interval)Applying forces to a Rigidbody
OnCollisionEnter / OnTriggerEnterWhen this object hits or enters another colliderDamage, collecting coins

Physics and collisions

csharp
using UnityEngine;

public class Ball : MonoBehaviour
{
    [SerializeField] private float jumpForce = 6f;
    private Rigidbody rb;
    private bool jumpRequested;
    private int coins;

    void Awake() => rb = GetComponent<Rigidbody>();          // cache once, not every frame

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space)) jumpRequested = true;   // read input every frame
    }

    void FixedUpdate()
    {
        if (jumpRequested)
        {
            rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);  // physics in FixedUpdate
            jumpRequested = false;
        }
    }

    void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("Coin"))
        {
            coins++;
            Destroy(other.gameObject);
            Debug.Log($"Coins: {coins}");
        }
    }
}
The coin needs a Collider with "Is Trigger" ticked and the tag Coin. GetComponent is cached in Awake because searching for components every frame is wasteful.

Prefabs and spawning

A prefab is a saved GameObject template (for example an enemy with all its components). Instantiate(prefab, position, Quaternion.identity) creates a copy in the scene at run time, and Destroy(obj) removes it. You never create MonoBehaviour scripts with new; Unity creates them when they are attached, or you call AddComponent<T>().

Common mistakes and fixes

  • Movement without Time.deltaTime: speed changes with frame rate. Multiply by Time.deltaTime.
  • Calling GetComponent or GameObject.Find every frame: slow. Cache references in Awake or Start.
  • Applying forces in Update: physics becomes jittery. Read input in Update, apply forces in FixedUpdate.
  • Script name and class name differ: Unity cannot attach the script. Keep them identical.
  • Writing new PlayerMove(): not allowed for MonoBehaviour. Attach it in the Editor or use AddComponent<PlayerMove>().

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Game development with Unity and C# · 1/7

Unity and C#

In this lesson you will use your C# skills to script games in Unity.

Prefer a video by a teacher? Find free videos on “Unity C# scripting tutorial for beginners MonoBehaviour Update Rigidbody” on YouTube ↗

In real life: A simple endless runner, like many mobile games

Endless-runner games (a character running forward, dodging obstacles, collecting coins) are a popular first project for Indian indie developers and in game-dev courses. The core is a few small scripts: one moves the runner forward at a steady speed, one spawns obstacles ahead, one counts coins.

csharp
using UnityEngine;

public class ObstacleSpawner : MonoBehaviour
{
    [SerializeField] private GameObject obstaclePrefab;
    [SerializeField] private Transform runner;
    [SerializeField] private float everySeconds = 1.5f;
    private float timer;

    void Update()
    {
        timer += Time.deltaTime;
        if (timer < everySeconds) return;
        timer = 0f;

        float lane = Random.Range(-1, 2) * 2f;      // -2, 0 or 2: three lanes
        Vector3 pos = new Vector3(lane, 0.5f, runner.position.z + 30f);
        Instantiate(obstaclePrefab, pos, Quaternion.identity);
    }
}
Random.Range(-1, 2) with ints gives -1, 0 or 1 (the upper bound is excluded). This is UnityEngine.Random, not System.Random.

Practice (0/4 done)

Task 1 · Question

Which class do Unity scripts usually inherit from?

Task 2 · Question

Why multiply movement by Time.deltaTime?

Task 3 · Question

Where should you apply forces to a Rigidbody?

Task 4 · Practice

In Unity, make a small scene: a plane for the ground, a sphere player with a Rigidbody, and five cube coins with trigger colliders tagged "Coin". Write a script that moves the player with the arrow keys (forces in FixedUpdate), counts collected coins, destroys each coin on pickup, and logs "You win!" when all five are collected.

Quick quiz

Question 1

1.What gives a GameObject its abilities in Unity?

Question 2

2.Which field appears in the Inspector?

Question 3

3.How should you create a MonoBehaviour script instance from code?

Question 4

4.Why cache GetComponent<Rigidbody>() in Awake?

Question 5

5.Does Unity always support the newest C# version shipped with .NET?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

What gives a GameObject its abilities in Unity?

Answer: Components attached to it

Unity uses composition: Transform, Collider, Rigidbody, scripts.

Which field appears in the Inspector?

Answer: [SerializeField] private float speed;

Public fields and [SerializeField] private fields are shown and saved by Unity.

How should you create a MonoBehaviour script instance from code?

Answer: gameObject.AddComponent<PlayerMove>()

MonoBehaviours are added to GameObjects, never created with new.

Why cache GetComponent<Rigidbody>() in Awake?

Answer: Searching for components every frame wastes time

Look it up once and reuse the reference.

Does Unity always support the newest C# version shipped with .NET?

Answer: No, Unity uses its own scripting runtime; check its manual for the supported C# version

Unity's supported C# version lags behind the latest .NET.

Which extra skills fit a Unity developer path?Related

Answer: Unity editor, physics, game maths

Game development needs engine and maths skills.

From Career paths with C# and .NET in India

Which .NET versions are Long Term Support (LTS)?Related

Answer: Even-numbered ones like 8 and 10

Even-numbered releases are LTS with three years of support.

From What C# and .NET are

Which device forwards a frame only out of the port where the destination MAC address is?Related

Answer: Switch

A switch learns MAC addresses per port and forwards frames only where needed.

From Network devices

Are C# methods virtual by default?Related

Answer: No, you must mark them virtual

Unlike Java, C# methods are non-virtual unless marked virtual.

From Inheritance: base and derived classes

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. This is the last topic of “Testing, tooling and Unity”. The module exam comes next.
  2. Module 9 exam: Testing, tooling and Unity · 12 questions · 20 min, without help. 4 topics of this module still to finish first.
  3. Then the next module, Interviews, portfolio and careers. 43 topics left in the course before the final exam.

← Previous: NuGet packages, solutions and project structure