๐ 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.
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.
โจ๏ธ
Code Challenge
+20 XP
Move the paddle frame-rate independently and clamp it:
๐ก 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;
}
}
}