Post-Midterm Workshop: Completing Blade Racer

🏁 Completing Blade Racer

From Prototype to Full Game

Game Programming — CSCI 3213

You've already built the hard parts. Now let's ship it.

📍 Where We Left Off

Your Blade Racer prototype has:

The mechanics are solid. But right now it's a prototype — not a game.

🎮 Prototype vs. Complete Game

Prototype

  • Starts mid-race with no context
  • No clear win or lose condition
  • Can't restart without the editor
  • No way to know who built it
  • Fun to build — awkward to hand to someone

Complete Game

  • Opens to a menu that sets expectations
  • Has a clear win and lose condition
  • Player can restart, quit, or return to menu
  • Credits give attribution and closure
  • A stranger can pick it up and play it

📋 Minimum Requirements

For full credit, your completed Blade Racer must include all three of the following:

1. Main Menu REQUIRED

A title screen where the experience begins. At minimum: a Play button and a route to Credits.

2. Complete Game Loop REQUIRED

The player can start a race, play to a defined win or lose condition, then return to the menu. No dead ends — every state connects back.

3. Credits Screen REQUIRED

A screen (or overlay) that credits the developer(s), any third-party assets used, and the course and institution.

Everything else is bonus. Get all three working and connected before exploring extras.

🎨 Your Game, Your Way

The requirements define the what — not the how. These are design decisions you get to own:

There is no wrong answer here. Build the game you want to build — just make sure all three required systems are complete and connected.

🗂️ Setting Up Your MVP Scenes

Before wiring any navigation, get your scene list locked in. Every SceneManager.LoadScene() call depends on these names and indices being stable.

File → Build Settings → drag scenes into the list:

Index Scene Name Purpose
0 MainMenu Always the first scene loaded on launch
1 GameScene The race — your core gameplay
2 CreditsScene Attribution and closure
3 DevTestScene Your prototype scene — dev access only (covered next)
Name your scenes before you write any navigation code. Renaming a scene after you've referenced it in SceneManager.LoadScene("OldName") will silently break at runtime — Unity won't warn you until you try to load it.

🔬 Your Prototype Scene as a Dev Tool

You've spent the whole semester in your original scene — full bike, drones, pickups, streaming track. Don't delete it. Rename it and keep it as a developer shortcut.

Rename it: SampleSceneDevTestScene

Add a Dev Mode button to your Main Menu:

// In MainMenuManager — wire to a button labeled "Dev Mode" or hide it public void OnDevModeClicked() { SceneManager.LoadScene("DevTestScene"); }
Pro habit: Keep the Dev Mode button visible while you're building. Once the game is complete and ready to submit, you can hide or remove it — but having it available throughout saves you from playing through menus hundreds of times during development.

🖥️ Step 1: Building Your Main Menu

What you need:

using UnityEngine.SceneManagement; public class MainMenuManager : MonoBehaviour { public void OnPlayClicked() { SceneManager.LoadScene("GameScene"); } public void OnCreditsClicked() { SceneManager.LoadScene("CreditsScene"); } public void OnQuitClicked() { Application.Quit(); } }
Keep it clean. A readable menu with clear buttons beats a flashy one that confuses players. Style it after you finish wiring everything up.

🔄 Step 2: The Game Loop

A complete game loop moves through defined states:

MenuCountdown / StartGameplayGame Over or VictoryRestart or Menu

Choose how the game ends — or invent your own:

Decide your end condition before you write any code. It determines what your GameManager needs to track and what events need to fire.

🗂️ Game State with GameManager

Your existing GameManager Singleton is the natural place to own overall game state — a straightforward extension of what you already built:

public enum GameState { Menu, Countdown, Playing, GameOver, Victory } public class GameManager : Singleton<GameManager> { public GameState CurrentState { get; private set; } public void SetState(GameState newState) { CurrentState = newState; EventBus.Publish("GameStateChanged", newState); } public void StartGame() => SetState(GameState.Playing); public void TriggerGameOver() => SetState(GameState.GameOver); public void TriggerVictory() => SetState(GameState.Victory); }
Pattern in Action: The Event Bus broadcasts state changes — your HUD, audio manager, and UI panels all respond without the GameManager ever knowing they exist.

💥 Game Over & Win Screens

Two solid approaches — pick what fits your design:

Option A: Separate Scenes

Option B: Canvas Overlay

// Game Over panel subscribing via the Event Bus void OnEnable() { EventBus.Subscribe("GameStateChanged", OnStateChanged); } void OnStateChanged(object state) { gameOverPanel.SetActive((GameState)state == GameState.GameOver); victoryPanel.SetActive((GameState)state == GameState.Victory); }

🎬 Step 3: Credits Screen

Your credits must include:

Implementation options:

// Simple credits auto-scroll IEnumerator ScrollCredits() { float elapsed = 0f; while (elapsed < scrollDuration) { creditsRect.anchoredPosition += Vector2.up * scrollSpeed * Time.deltaTime; elapsed += Time.deltaTime; yield return null; } SceneManager.LoadScene("MainMenu"); }

🔧 Your Patterns Are Already the Tools

You don't need to invent new architecture — what you built is designed for exactly this:

Feature Pattern(s) You Already Have
Game state flow (menu → play → game over) GameManager Singleton + Event Bus
UI reacting to player death or victory Event Bus ("GameStateChanged" event)
Pausing without breaking the Object Pool State Pattern + Time.timeScale = 0
Restart without memory leaks or ghost objects Object Pool (reset and reuse, don't Destroy)
Live score updates to the HUD Observer Pattern or Event Bus
Difficulty-scaled enemy AI Strategy Pattern (swap drone behavior at runtime)
The patterns you studied aren't just for Blade Racer's mechanics — they're how professional games are structured end to end.

💡 Ideas to Take It Further

Once your three required systems are complete and connected, here are directions worth exploring:

Scope carefully. One polished bonus feature beats three half-finished ones. Finish the loop first.

💻 Workshop: Build Time

Recommended order of attack:

  1. Set up your scenes in Build Settings — Create MainMenu, GameScene, CreditsScene, and rename your prototype to DevTestScene. Lock in names before writing any navigation code.
  2. Decide your end condition — Crash limit? Distance? Score? Write it down before touching code.
  3. Build the Main Menu scene — Title, Play, Credits, and Dev Mode buttons. Wire up SceneManager.LoadScene.
  4. Extend GameManager with game state — Add the GameState enum and SetState(). Connect your crash/win detection to it.
  5. Add Game Over and Win screens — Show the result. Offer Restart and Return to Menu on both.
  6. Build the Credits scene or overlay — Simple is fine. Make sure it navigates back to the menu.
  7. Test the full loop from a cold start — Menu → play → game over → restart → game over → menu → credits → menu. Every path must close.

📝 Grading & Deliverables

Submitted via GitHub — your final commit must include:

Required for Full Credit:

  • ✅ Main Menu scene with Play button and Credits navigation
  • ✅ A clearly defined win condition and a clearly defined lose condition
  • ✅ Game Over and Victory screens with Restart and Return to Menu options
  • ✅ Credits screen with your name, course info, and asset attribution
  • ✅ Full loop playable: menu → race → outcome → menu
  • ✅ No dead ends — every scene and state can return to the menu
Test it like a first-time player would. Launch the build, go through every path, and make sure nothing gets stuck or crashes. Then commit.

🏁 Let's Finish the Race

What we're building today:

Keep in mind:

You built a game engine. Now let's build a game. 🚀