🔷 My First Unity Game · Episode 1 of 8 · See All Episodes
🏓 Episode 1 · Beginner · Your First Unity Project

Engine Time!
Unity Pong

Meet Unity, the engine behind Hollow Knight and Cuphead-scale indies: scenes, GameObjects, components and your first C# scripts, assembled into Pong with real physics.

👶 Ages 12+ ⏱️ ~2 Hours 🔷 Unity & C# ✓ Free
🧩 GameObjects 🔧 Components 📜 C# scripts ⚛️ Rigidbody2D 💥 OnCollisionEnter 🎨-🖥️ UI Text
⭐
0 XP
Level 1
🔥0
Your Progress 0 / 6 steps
🦊
Lumo says: take this one step at a time. Fill in each blank and watch the ball bounce in the live preview, then play it yourself.
📦
Reference project: download the finished code files used in this workshop: ⬇ unity-pong-workshop-reference.zip. Every code block also has a Copy button.
1
🧩
Install & The Unity Mindset
Hub, editor tour, and GameObject + Component thinking
Active
🎯
Goal for this step

Set up Unity and understand its core idea: everything is components.

  • 1Install Unity Hub (unity.com), then an LTS editor version. Personal licence = free.
  • 2New Project → 2D (Built-In) template, name it Pong.
  • 3The tour: Hierarchy (what is in the scene), Scene view (arrange it), Game view (play it), Inspector (edit the selected thing), Project (all files).
  • 4THE idea: a GameObject is an empty shell; Components (sprite, physics, YOUR scripts) give it behaviour. A paddle = GameObject + SpriteRenderer + Collider + your script.
  • 5Create → 2D Object → Sprite → Square. Scale it into a paddle (0.3, 2, 1) in the Inspector. That is your first component edit!
👨‍👧
Parent note: Unity Personal is free for hobby and learning use. Projects are large (gigabytes), a machine with 8 GB+ RAM and some disk space is recommended.
✏️
Fill in the Blanks
+15 XP
A is an empty container that gains behaviour from attached . The panel used to edit the selected object is the .
🧠
Knowledge Check
+15 XP
The component model means a "paddle" is…
AA special paddle asset Unity ships
BAn ordinary GameObject wearing a sprite, a collider and your movement script, behaviour by combination
CA C# class you must write from scratch
2
📜
Your First C# Script
PaddleMovement.cs with Update and Input
Locked
🎯
Goal for this step

Write a C# MonoBehaviour that moves the paddle.

  • 1Project panel → Create → C# Script → PaddleMovement. Double-click to open (VS or VS Code).
  • 2A MonoBehaviour has magic methods: Start() (once, on spawn) and Update() (every frame, the Step event / game loop of Unity).
  • 3Input.GetAxisRaw("Vertical") reads W/S and arrows as -1/0/1 in one call.
  • 4Move with transform.position, scaled by Time.deltaTime, Unity’s dt (you learned WHY in C++!).
  • 5Drag the script ONTO the paddle GameObject, attaching code IS adding a component. Press Play ▶️-▶️ and drive.
PaddleMovement.cs
using UnityEngine;

public class PaddleMovement : MonoBehaviour
{
    public float speed = 8f;
    public KeyCode upKey = KeyCode.W;
    public KeyCode downKey = KeyCode.S;

    void Update()
    {
        float move = 0f;
        if (Input.GetKey(upKey))   move = 1f;
        if (Input.GetKey(downKey)) move = -1f;

        Vector3 pos = transform.position;
        pos.y += move * speed * Time.deltaTime;
        pos.y = Mathf.Clamp(pos.y, -3.6f, 3.6f);
        transform.position = pos;
    }
}
💡
public fields appear as editable boxes in the Inspector, speed and keys are tweakable without touching code. Designers live in those boxes.
🧩
Put the Code in Order
+20 XP
Drag these lines into the correct order to move and clamp the paddle:
transform.position = pos;
pos.y += move * speed * Time.deltaTime;
Vector3 pos = transform.position;
pos.y = Mathf.Clamp(pos.y, -3.6f, 3.6f);
⌨️
Code Challenge
+20 XP
Move the paddle frame-rate independently and clamp it:
PaddleMovement.cs
pos.y += move * speed * Time.;
pos.y = Mathf.(pos.y, -3.6f, );
💡 Hint: Unity’s per-frame time makes speed FPS-proof; the clamp function pins the paddle between the court edges.
🧠
Knowledge Check
+15 XP
Why did making speed public matter?
APrivate variables crash
BIt appears in the Inspector, tune the feel live in Play mode without editing code
CPublic is faster
3
⚛️
Physics Ball
Rigidbody2D, colliders and a bouncy material
Locked
🎯
Goal for this step

Let Unity’s physics engine drive the ball, no movement code at all.

  • 1Ball: a Square sprite scaled 0.35. Add TWO components: Rigidbody2D (physics body) and BoxCollider2D (solid shape). Paddles get colliders too (no rigidbody, they are kinematic walls).
  • 2Rigidbody2D settings: Gravity Scale 0 (no falling in Pong!), Collision Detection Continuous (fast balls cannot tunnel).
  • 3Perfect bounce: create a Physics Material 2D, Bounciness 1, Friction 0, assign to the ball collider.
  • 4Launch from a tiny script: one line in Start gives it velocity. Physics does EVERYTHING else, bounces included.
  • 5Top/bottom walls: two thin sprites with colliders. Play: it is already almost Pong.
BallLauncher.cs
using UnityEngine;

public class BallLauncher : MonoBehaviour
{
    public float speed = 6f;
    Rigidbody2D rb;

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

    public void Launch()
    {
        float dirX = Random.value < 0.5f ? -1f : 1f;
        float dirY = Random.Range(-0.6f, 0.6f);
        rb.linearVelocity = new Vector2(dirX, dirY).normalized * speed;
    }
}
✏️
Fill in the Blanks
+15 XP
Physics needs two components: a body and a collider. Pong disables falling by setting Gravity Scale to , and perfect rebounds come from a physics material with Bounciness .
🧠
Knowledge Check
+15 XP
The ball has NO movement code in Update, yet bounces perfectly. Who is doing the work?
AThe paddle scripts
BUnity’s physics engine, you configured behaviour with components instead of coding it
CThe camera
4
💥
Goals & Collision Messages
Trigger zones, OnTriggerEnter2D and scoring
Locked
🎯
Goal for this step

Detect goals with trigger zones and keep score.

  • 1Two invisible goal zones just off the left/right edges: sprites with BoxCollider2D set to Is Trigger (things pass through, but Unity tells you).
  • 2A GameManager empty GameObject holds the score script.
  • 3The zone’s script: OnTriggerEnter2D(Collider2D other) fires when the ball enters, GameMaker’s collision event, C# spelling.
  • 4CompareTag("Ball") checks WHAT entered (set the Ball’s tag in the Inspector first!).
  • 5On goal: tell the manager who scored, recentre the ball, relaunch.
GoalZone.cs
using UnityEngine;

public class GoalZone : MonoBehaviour
{
    public GameManager manager;
    public bool isLeftGoal;

    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Ball"))
        {
            manager.ScorePoint(isLeftGoal);
            other.transform.position = Vector3.zero;
            other.GetComponent<BallLauncher>().Launch();
        }
    }
}
⌨️
Code Challenge
+20 XP
React only to the ball entering the goal:
GoalZone.cs
void (Collider2D other)
{
    if (other.("Ball"))
        manager.ScorePoint(isLeftGoal);
}
💡 Hint: The trigger-entry magic method, then the tag check that filters out paddles and walls.
🧠
Knowledge Check
+15 XP
A trigger collider differs from a normal collider because…
AIt is invisible
BObjects pass THROUGH it, but the enter/exit events still fire, perfect for zones and pickups
CIt only works on balls
5
🏓
Score UI & Game Manager
Canvas, TextMeshPro and first-to-7
Locked
🎯
Goal for this step

Draw the score on screen and end the match at 7.

  • 1UI lives on a Canvas: GameObject → UI → Text - TextMeshPro (import Essentials when asked). Two texts, anchored top-centre, big font.
  • 2GameManager script: two ints, a ScorePoint method updating the texts, and a win check at 7 showing a winner banner (a third, hidden text).
  • 3Wire references by DRAGGING in the Inspector: the text objects into the manager’s public fields, the manager into each goal zone. Visual dependency injection!
  • 4Time.timeScale = 0 pauses the whole engine on game over, one line.
GameManager.cs
using UnityEngine;
using TMPro;

public class GameManager : MonoBehaviour
{
    public TMP_Text leftText, rightText, winnerText;
    int leftScore, rightScore;

    public void ScorePoint(bool leftGoalWasHit)
    {
        if (leftGoalWasHit) rightScore++;
        else                leftScore++;

        leftText.text  = leftScore.ToString();
        rightText.text = rightScore.ToString();

        if (leftScore == 7 || rightScore == 7)
        {
            winnerText.text = (leftScore == 7 ? "LEFT" : "RIGHT")
                              + " PLAYER WINS!";
            winnerText.gameObject.SetActive(true);
            Time.timeScale = 0f;      // freeze the game
        }
    }
}
✏️
Fill in the Blanks
+15 XP
All screen UI lives under a object. Freezing the entire game is one line: Time. = 0.
🧠
Knowledge Check
+15 XP
Dragging objects into Inspector fields (instead of finding them in code) gives you…
ASlower startup
BExplicit, visible wiring, you SEE what talks to what, and designers can rewire without code
CAutomatic multiplayer
6
🏓
AI Paddle & Build
A beatable opponent, then export a real .exe
Locked
🎯
Goal for this step

Add the classic flawed AI and BUILD your game as a real application.

  • 1AIPaddle.cs: chase ball.position.y with a dead zone and capped speed, the SAME design you wrote in Java, C++, GML. Engines change; design does not.
  • 2The finale: File → Build Profiles → Build. Unity produces an actual .exe (or Mac/Linux app), your game as REAL SOFTWARE, no editor needed.
  • 3Send it to someone. Watch them play a thing you made in an industry engine.
  • 4Episode 2 (2D Platformer) already awaits in the series, you now speak Unity.
AIPaddle.cs
using UnityEngine;

public class AIPaddle : MonoBehaviour
{
    public Transform ball;
    public float speed = 5f;       // slower than the player!
    public float deadZone = 0.4f;

    void Update()
    {
        float diff = ball.position.y - transform.position.y;
        if (Mathf.Abs(diff) > deadZone)
        {
            Vector3 pos = transform.position;
            pos.y += Mathf.Sign(diff) * speed * Time.deltaTime;
            pos.y = Mathf.Clamp(pos.y, -3.6f, 3.6f);
            transform.position = pos;
        }
    }
}
⌨️
Code Challenge
+20 XP
The eternal AI recipe, Unity spelling:
AIPaddle.cs
if (Mathf.(diff) > deadZone)
    pos.y += Mathf.(diff) * speed * Time.deltaTime;
💡 Hint: Distance size, then pure direction, the exact pair you used in GML (abs/sign) and C++.
🧠
Knowledge Check
+15 XP
You have now built Pong in FOUR technologies. The thing that transferred 100% every time was…
AThe file extensions
BGame design and logic: loops, input, collision response, flawed AI, states, the thinking IS the skill
CThe keyboard shortcuts
🎉🏆🎮✨🎉
Workshop Complete!
Scenes, components, physics and C#, the Unity mental model, learned on Pong. The rest of the series builds on exactly this!
0
Total XP
1
Level
0
Best Streak
0%
Accuracy
Episode 2: 2D Platformer →
⭐ View My Progress & Certificates

This workshop was free and took many hours to build. If it helped you learn something new, consider supporting the project.

☕ Support on Ko-fi
🛠️ Build Pong in the Unity Studio Set it up in the browser, play it live, then export the real C# scripts to Unity. No install. Open the Studio →