Singleton Pattern & Design Patterns Roadmap

Design Patterns Roadmap

The Singleton Pattern đŸŽ¯

CSCI 3213 - Game Programming

Your journey through professional game patterns begins!

Today's Content

📚 Based on Chapter 4

Implementing a Game Manager with the Singleton

From: Game Development Patterns with Unity 2021 (2nd Edition)
By David Baron

Remember: Baron's book is available at Dulaney Browne Library. Today we're starting our practical pattern implementations!

Today's Agenda

What We'll Cover

  1. Part 1: Semester Patterns Roadmap (10 patterns)
  2. Part 2: Understanding the Singleton Pattern
  3. Part 3: Implementing a Game Manager
  4. Part 4: Testing the Singleton
  5. Homework: Complete implementation & video submission
Time Management: If we run short on time, you'll complete the implementation as homework. Either way, you'll need to test with 5 scenes!

Developer's Note: "Never Panic Early"

âš ī¸ What to Expect During Implementation

As we implement this pattern, we'll be creating multiple files in a specific order. You will see errors in Unity and your IDE until all files are complete.

How to Handle Development Errors

  • Don't Ignore: Note the errors - they're telling you something
  • Don't Panic: These are expected until all files are created
  • Stay Calm: Follow the implementation order and errors will resolve

As Apollo 13's Fred Haise said: "Never Panic Early"

This is a critical skill for software development. Note problems, but stay focused on the implementation path.

Part 1: Design Patterns Roadmap

10 Patterns, 10 Weeks

Each pattern solves a specific game development problem.
Each week, we'll learn the theory and implement it in Blade Racer.

The Journey

By the end of this course, you'll have a complete game built with professional-grade architecture using industry-standard design patterns.

Foundational Patterns (Weeks 2-6)

CHAPTER 4 â€ĸ WEEK 2
Singleton Pattern

Implementing a Game Manager

CHAPTER 5 â€ĸ WEEK 3
State Pattern

Managing Character States

CHAPTER 6 â€ĸ WEEK 4
Event Bus Pattern

Managing Game Events

CHAPTER 7 â€ĸ WEEK 5
Command Pattern

Implementing a Replay System

CHAPTER 8 â€ĸ WEEK 6
Object Pool Pattern

Optimizing Performance

Behavioral Patterns (Weeks 7-11)

CHAPTER 9 â€ĸ WEEK 7
Observer Pattern

Decoupling Components

CHAPTER 10 â€ĸ WEEK 8
Visitor Pattern

Implementing Power-Ups

CHAPTER 11 â€ĸ WEEK 9
Strategy Pattern

Implementing a Drone

CHAPTER 12 â€ĸ WEEK 10
Decorator Pattern

Weapon System Implementation

CHAPTER 13 â€ĸ WEEK 11
Spatial Partition Pattern

Implementing a Level Editor

Your Learning Path

Pattern Categories

Creational: Singleton, Object Pool
Behavioral: State, Command, Observer, Visitor, Strategy
Structural: Decorator, Spatial Partition
Architectural: Event Bus
Don't worry about memorizing! We'll learn each pattern in context when we need it for Blade Racer.

Part 2: The Singleton Pattern

What is a Singleton?

A class that ensures only one instance exists
and provides global access to that instance.

Real-World Analogy

Like a country having only one president at a time. Everyone knows who the president is, and there can only be one person in that role.

The Problem Singleton Solves

❌ Without Singleton

// Player needs game manager GameManager manager = GameObject.Find("GameManager") .GetComponent<GameManager>(); // Enemy also needs game manager GameManager manager = GameObject.Find("GameManager") .GetComponent<GameManager>(); // UI also needs game manager... đŸ˜Ģ

Problems: Repeated code, slow GameObject.Find(), no guarantee of single instance

✅ With Singleton

// Anywhere in your code: GameManager.Instance.StartGame(); GameManager.Instance.PauseGame();

Benefits: Clean, fast, guaranteed single instance, globally accessible

When to Use the Singleton Pattern

✅ Perfect For

  • Game Manager
  • Audio Manager
  • Input Manager
  • Save/Load Manager
  • Network Manager
  • Pool Manager

❌ Not Suitable For

  • Multiple instances needed
  • Player characters
  • Enemies
  • Projectiles
  • UI elements (usually)
  • Temporary objects
Rule of Thumb: If you need global access and only ONE instance should exist, use Singleton.

Singleton: Benefits & Drawbacks

✅ Benefits

  • Single Instance: Guaranteed only one exists
  • Global Access: Available from anywhere
  • Lazy Instantiation: Created when needed
  • Clean Code: No repeated GameObject.Find()
  • Performance: Fast direct access

âš ī¸ Drawbacks

  • Global State: Can create hidden dependencies
  • Testing: Harder to unit test
  • Coupling: Code becomes dependent on singleton
  • Overuse: Can become anti-pattern if abused
  • Threading: Not thread-safe by default
âš ī¸ Important: Don't make everything a Singleton! Use it judiciously for true manager classes.

Singleton Pattern Structure

Core Components

1. Private Static Instance

Stores the single instance of the class

Game Example: Like having a single high score tracker that stores the current record - only one "official" score needs to exist, and everyone references the same one.

2. Public Static Accessor

Provides global access point (Instance property)

Game Example: Any script can call GameManager.Instance.GetCurrentLevel() without needing to find or pass references around - just like checking what round the game is on.

3. Private Constructor (optional)

Prevents external instantiation with new keyword

When to use: Use for pure C# classes (non-MonoBehaviour) to enforce singleton pattern strictly. Skip for MonoBehaviours - Unity needs public/protected constructors for component creation. Instead, use Awake() to enforce single instance.

Game Example: A SaveManager that's pure C# would use private constructor. But GameManager (MonoBehaviour) enforces uniqueness in Awake() instead.

4. Instance Check

Creates instance if it doesn't exist (lazy instantiation)

Game Example: First time any script tries to play audio via AudioManager.Instance, the manager automatically creates itself if not already in the scene - no manual setup required.

Basic Singleton Implementation

📖 Instructional Example - Manual Singleton Pattern

This code demonstrates how the Singleton pattern works internally.
Don't create this file yet! This is for learning how singletons work.
Later, we'll build a better version using the generic Singleton<T> base class.

using UnityEngine; public class GameManager : MonoBehaviour { // 1. Private static instance variable private static GameManager _instance; // 2. Public static accessor property public static GameManager Instance { get { if (_instance == null) { // Find existing instance in scene _instance = FindObjectOfType<GameManager>(); if (_instance == null) { // Create new GameObject with GameManager GameObject go = new GameObject("GameManager"); _instance = go.AddComponent<GameManager>(); } } return _instance; } } void Awake() { // Ensure only one instance exists if (_instance != null && _instance != this) { Destroy(this.gameObject); } else { _instance = this; } } }

Persistent Singleton (Don't Destroy)

📖 Instructional Example - Persistence Concept

This slide shows how DontDestroyOnLoad() makes objects persist across scenes.
This is still part of the learning example - we'll use this concept in our production code later.
The generic Singleton<T> class (next slide) already includes this functionality!

void Awake() { if (_instance != null && _instance != this) { // Destroy duplicate Destroy(this.gameObject); } else { _instance = this; // Persist across scene loads! DontDestroyOnLoad(this.gameObject); } }

DontDestroyOnLoad()

Keeps the GameObject alive when loading new scenes. Perfect for managers that need to persist throughout the game!

Testing Note: You'll test this with 5 scenes to see it persist!

âš™ī¸ Rider Setup (One-Time Configuration)

Configure Rider to Stop Auto-Adding Namespaces

Before we write production code, let's configure Rider so it doesn't automatically add namespace declarations to your files. Unity scripts typically don't need namespaces unless you're building a large-scale project.

Step-by-Step Instructions:

  1. Open Settings: File → Settings (or Ctrl+Alt+S / Cmd+,)
  2. Navigate to: Editor → File Templates → C#
  3. Edit Templates: Remove namespace and corresponding curly brackets from class, interface, component, and enum.
  4. Navigate to: Editor → File Templates → Unity
  5. Edit Templates: Remove namespace and corresponding curly brackets from all sections that have them. It's alot. It's tedious. You only have to do it once.
  6. Click: Save
  7. Reopen Settings
  8. Click the dropdown by Save
  9. Click: This Computer
What this does: Prevents Rider from automatically wrapping your code in namespace YourNamespace; declarations. This keeps Unity scripts clean and simple for our course.

Generic Singleton (Reusable Template)

📁 File Structure Note - PRODUCTION CODE

Create a new file: Assets/Scripts/Core/Singleton.cs
This is a reusable generic base class that ANY class can inherit from to become a singleton.
This is the recommended approach in production!
âš ī¸ This code goes into your Unity project and will be used throughout Blade Racer.

using UnityEngine; public class Singleton<T> : MonoBehaviour where T : Component { private static T _instance; public static T Instance { get { if (_instance == null) { _instance = FindObjectOfType<T>(); if (_instance == null) { GameObject obj = new GameObject(); obj.name = typeof(T).Name; _instance = obj.AddComponent<T>(); } } return _instance; } } public virtual void Awake() { if (_instance == null) { _instance = this as T; DontDestroyOnLoad(gameObject); } else { Destroy(gameObject); } } }

Understanding the Class Declaration

public class Singleton<T> : MonoBehaviour where T : Component

Singleton<T> - Generic class with type parameter T

Means: T is a placeholder for any type you specify later

: MonoBehaviour - Inherits from Unity's MonoBehaviour

Means: Can be attached to GameObjects like any Unity script

where T : Component - Generic constraint

Means: T must be a Component type (MonoBehaviour, Transform, etc.)

public virtual void Awake() - Virtual method

Means: Child classes can override this method to add their own initialization logic

Why? GameManager needs its own Awake() code, but must also call base.Awake() to ensure singleton setup runs first

Example Usage:

class GameManager : Singleton<GameManager>

Here T = GameManager

Generics Power! Remember from our crash course? Now any class can become a Singleton!

Using the Generic Singleton

📖 Instructional Example

GameManager - Production Code you will build in a few slides. Not now.
AudioManager & Player - Example code only (demonstrates the pattern, not for Blade Racer)
These examples show how ANY manager class can use the Singleton pattern.

// Simply inherit from Singleton<T> public class GameManager : Singleton<GameManager> { public void StartGame() { Debug.Log("Game Started!"); } } public class AudioManager : Singleton<AudioManager> { public void PlaySound(string soundName) { Debug.Log("Playing: " + soundName); } }
// Use them anywhere! public class Player : MonoBehaviour { void Start() { GameManager.Instance.StartGame(); AudioManager.Instance.PlaySound("PlayerSpawn"); } }

Part 3: Designing a Game Manager

What Does a Game Manager Do?

  • 🎮 Initialize game systems
  • â¸ī¸ Handle game state (Start, Pause, Resume, End)
  • 📊 Track game-wide data (score, time, level)
  • 🔄 Coordinate between systems
  • 💾 Manage scene transitions
For Blade Racer: Our Game Manager will initialize the race, track time, handle pause/resume, and manage race completion.

Game Manager Implementation

📁 File Structure Note - PRODUCTION CODE

All code in the next several slides goes into: Assets/Scripts/Managers/GameManager.cs
âš ī¸ Build this complete GameManager for your Blade Racer project.

Building It Step by Step

Let's break down the Game Manager implementation piece by piece. Each section serves a specific purpose in managing your game's lifecycle.

What We'll Build

  1. Class Setup: State variables and inheritance
  2. Initialization: Awake and Start lifecycle
  3. Game Control: Start and Pause methods
  4. Game Loop: Resume and Update tracking
Follow Along: Next slides show each piece with explanations!

Game Manager - Class Setup

using UnityEngine; public class GameManager : Singleton<GameManager> { // Game state variables private bool _isGameActive; private float _gameTime; // Methods go here... }

How This Works

Inheritance: By inheriting from Singleton<GameManager>, we get all the singleton behavior automatically!

State Variables:

  • _isGameActive - Tracks if game is running or paused
  • _gameTime - Tracks total elapsed game time

Game Use: In Blade Racer, these track whether the race is active and how long the player has been racing.

Game Manager - Initialization

public override void Awake() { base.Awake(); // Call Singleton Awake } void Start() { InitializeGame(); } private void InitializeGame() { Debug.Log("[GameManager] Initializing..."); _isGameActive = false; _gameTime = 0f; }

How This Works

Awake(): We override Awake but call base.Awake() to ensure the singleton setup happens first.

Start(): Unity calls this after all Awake methods complete. Perfect for initialization!

InitializeGame(): Sets default values - game starts paused with time at zero.

Game Use: When Blade Racer loads, this prepares the game state before the race countdown begins.

Game Manager - Game Control

public void StartGame() { Debug.Log("[GameManager] Game Started!"); _isGameActive = true; } public void PauseGame() { Debug.Log("[GameManager] Game Paused"); _isGameActive = false; Time.timeScale = 0f; }

How This Works

StartGame(): Sets _isGameActive to true, allowing the game loop to run. Called when race begins!

PauseGame(): Stops game and sets Time.timeScale = 0 which freezes all time-based operations in Unity.

Game Use: Any script can call GameManager.Instance.PauseGame() when ESC is pressed. UI, enemies, physics - everything pauses!

Game Manager - Game Loop

public void ResumeGame() { Debug.Log("[GameManager] Game Resumed"); _isGameActive = true; Time.timeScale = 1f; } void Update() { if (_isGameActive) { _gameTime += Time.deltaTime; } }

How This Works

ResumeGame(): Opposite of pause - reactivates the game and restores normal time flow with Time.timeScale = 1.

Update(): Runs every frame. Only tracks time when game is active, using Time.deltaTime (time since last frame).

Game Use: Track total race time in Blade Racer. Display on UI, use for leaderboards, or trigger time-based events.

C# Concept: The 'override' Keyword

📖 Instructional Example - C# Language Concept

This slide explains the C# override keyword used in your production GameManager code.
The examples here are for learning purposes - you already used this in your GameManager.cs.

// In Singleton<T> base class: public virtual void Awake() { // Singleton setup code... }
// In GameManager (child class): public override void Awake() { base.Awake(); // Our custom code... }

What Does 'override' Mean?

Override lets a child class replace or extend a method from its parent class.

The Rules:

  1. Parent class marks method as virtual (meaning "you can override this")
  2. Child class uses override to replace that method
  3. Use base.MethodName() to call the parent's version first

Why we need it: Singleton's Awake() sets up the singleton behavior. GameManager's Awake() needs to do that AND add custom setup. Override lets us do both!

Override in Action: The Flow

What Happens When GameManager Starts?

Step 1: Unity calls Awake()

Unity sees GameManager component and calls its Awake() method

Step 2: GameManager.Awake() runs

First line is base.Awake() - this calls the parent (Singleton) version

public override void Awake() { base.Awake(); ← Jumps to parent! }
Step 3: Singleton<T>.Awake() runs

Checks if instance exists, sets DontDestroyOnLoad, handles duplicates

Step 4: Returns to GameManager.Awake()

After parent finishes, continues with any custom code below base.Awake()

Key Insight: Always call base.Awake() FIRST so the singleton setup happens before your custom code runs!

Common Mistake: Forgetting 'override'

❌ Without Override

// Wrong! Missing 'override' public void Awake() { // This WON'T call parent! // Singleton setup SKIPPED! }

Result: C# compiler error! Can't redefine a method without 'override' keyword.

Error message: "...hides inherited member. Use the new keyword if hiding was intended, or use override."

✅ With Override

// Correct! public override void Awake() { base.Awake(); // Parent runs first ✓ // Then our code ✓ }

Result: Works perfectly! Singleton setup happens, then your custom code runs.

Best Practice: Visual Studio Code will suggest 'override' when you start typing parent methods.

Remember: If parent has virtual, child needs override!

Unity Concept: Time.deltaTime & Time.timeScale

📖 Instructional Example - Unity API Explanation

This slide explains Unity's Time system used in your production GameManager code.
The examples here demonstrate concepts - you already use Time.deltaTime and Time.timeScale in GameManager.cs.

Time.deltaTime

What it is: The time (in seconds) since the last frame was rendered.

Typical value: Around 0.016 seconds (60 FPS) or 0.033 seconds (30 FPS)

void Update() { // Track total time _gameTime += Time.deltaTime; // Move at 5 units per second transform.position += Vector3.forward * 5f * Time.deltaTime; }
Why use deltaTime? Makes movement frame-rate independent! Fast PC (120 FPS) and slow PC (30 FPS) move at same speed.

Time.timeScale

What it is: A multiplier for how fast time passes in Unity.

Default value: 1.0 (normal speed)

// Normal speed Time.timeScale = 1f; // Slow motion (50% speed) Time.timeScale = 0.5f; // Fast forward (2x speed) Time.timeScale = 2f; // Freeze time (PAUSE!) Time.timeScale = 0f;
Important: timeScale affects physics, animations, particle systems - basically everything time-based!

How Time.timeScale Affects Your Game

timeScale Values & Effects

Time.timeScale = 0f (PAUSED)

â€ĸ Update() still runs, but Time.deltaTime = 0

â€ĸ Physics frozen, animations stopped, particles frozen

â€ĸ Perfect for pause menus!

_gameTime += Time.deltaTime; // Adds 0, stops counting!
Time.timeScale = 1f (NORMAL)

â€ĸ Default game speed

â€ĸ Time.deltaTime equals real frame time (~0.016s at 60 FPS)

â€ĸ Everything runs as expected

Time.timeScale = 0.5f (SLOW MOTION)

â€ĸ Game runs at half speed

â€ĸ Time.deltaTime is halved (0.008s instead of 0.016s)

â€ĸ Great for bullet-time effects!

Time.timeScale = 2f (FAST FORWARD)

â€ĸ Game runs at double speed

â€ĸ Time.deltaTime is doubled (0.032s instead of 0.016s)

â€ĸ Useful for speed-up power-ups or simulation fast-forward

Putting It Together: Pause & Resume

// Our PauseGame() method: public void PauseGame() { Debug.Log("[GameManager] Game Paused"); _isGameActive = false; Time.timeScale = 0f; ← Freeze time! } // Our ResumeGame() method: public void ResumeGame() { Debug.Log("[GameManager] Game Resumed"); _isGameActive = true; Time.timeScale = 1f; ← Restore time! } // Update() respects the pause: void Update() { if (_isGameActive) ← Optional check { // Even if this runs, deltaTime = 0 _gameTime += Time.deltaTime; } }

How The Pause Works

Step 1: Player presses ESC, calls PauseGame()

Step 2: Set _isGameActive = false (our custom flag)

Step 3: Set Time.timeScale = 0 (Unity's time freeze)

Result: All physics, animations, and time-based code freezes!

Game Example: In Blade Racer, when you pause:

  • Bike stops moving (physics frozen)
  • Wheel animations freeze
  • Enemies stop chasing
  • Timer stops counting
  • BUT: UI still works (canvas updates independently!)
Pro Tip: You can use Time.unscaledDeltaTime for things that should keep running during pause (like UI animations or pause menu effects)!

Part 4: Testing the Singleton

Testing Strategy

  1. Create Test Script: TestGameManager.cs
  2. Call Instance: Verify global access works
  3. Test Methods: Call StartGame(), PauseGame(), etc.
  4. Multiple Scenes: Load 5 different scenes
  5. Verify Persistence: Confirm same instance across scenes
Your Homework: Create 5 test scenes and verify the Game Manager persists across all of them!

Test Script Example

📁 File Structure Note - TESTING CODE

Create a new file: Assets/Scripts/Testing/TestGameManager.cs
This script is for testing your Singleton implementation across multiple scenes.
âš ī¸ This is temporary testing code - create it for your homework assignment, then you can remove it later.

using UnityEngine; using UnityEngine.SceneManagement; public class TestGameManager : MonoBehaviour { void Start() { // Test global access Debug.Log("Testing GameManager Singleton..."); // Start the game GameManager.Instance.StartGame(); } void Update() { // Test pause/resume if (Input.GetKeyDown(KeyCode.P)) { GameManager.Instance.PauseGame(); } if (Input.GetKeyDown(KeyCode.R)) { GameManager.Instance.ResumeGame(); } // Load next scene to test persistence if (Input.GetKeyDown(KeyCode.N)) { int nextScene = SceneManager.GetActiveScene().buildIndex + 1; if (nextScene < SceneManager.sceneCountInBuildSettings) { SceneManager.LoadScene(nextScene); } } } }

Setting Up Test Scenes

Step-by-Step Setup

  1. Create 5 new scenes: Scene1, Scene2, Scene3, Scene4, Scene5
  2. Add all scenes to Build Profiles (File → Build Profiles)
  3. In Scene1: Add GameObject with GameManager script
  4. In each scene: Add different colored background (visual verification)
  5. In each scene: Add GameObject with TestGameManager script
  6. Add UI Text showing scene name (optional but helpful)
Visual Test: Different background colors help you see when scenes change!

Testing Checklist

✅ Verify These Behaviors

✓ GameManager.Instance is accessible from any script
✓ Only ONE instance exists (check Hierarchy)
✓ Instance persists across scene loads
✓ StartGame() logs correctly
✓ PauseGame() freezes time (press P)
✓ ResumeGame() restores time (press R)
✓ Scene loads work (press N for next scene)

Common Singleton Issues

❌ Common Problems

  • Multiple instances: Check Awake() logic
  • Null reference: Instance accessed before creation
  • Destroyed on load: Missing DontDestroyOnLoad()
  • Wrong instance: Not calling Destroy() on duplicates

✅ Solutions

  • Destroy duplicates: if (_instance != this)
  • Lazy instantiation: Create in getter if null
  • Persist properly: DontDestroyOnLoad(gameObject)
  • Debug logs: Verify Awake() calls
Debug Tip: Add Debug.Log() in Awake() to see when instances are created/destroyed!

Hands-On Implementation đŸ’ģ

In-Class Challenge (If Time Permits)

Let's implement together:

  1. Create Singleton<T> base class
  2. Create GameManager : Singleton<GameManager>
  3. Add StartGame(), PauseGame(), ResumeGame() methods
  4. Create test script to call methods
  5. Test in Play mode
Note: If we don't finish in class, complete this as homework!

Gaming History Moment đŸ•šī¸

Nintendo NES & Quality Control (1985)

After the 1983 video game crash nearly destroyed the industry, retailers refused to stock game consoles. Nintendo faced an uphill battle launching the NES in North America in 1985. Their solution? The Nintendo Seal of Quality - a strict quality control program where Nintendo tested and approved every game before release.

Nintendo's Seal of Quality

Unlike Atari's open platform (which led to disasters like E.T.), Nintendo implemented a lockout chip that prevented unauthorized cartridges from running. Publishers had to go through Nintendo for approval, limiting releases to maintain quality. Only ONE version of each game could exist on the platform.

Connection to Singleton Pattern

Nintendo's Seal of Quality is like the Singleton pattern - ensuring only ONE official, approved instance exists. Just as our GameManager ensures only one instance manages the game state, Nintendo ensured only one approved version of each game reached consumers. This "single source of truth" approach saved the video game industry!

Learn More: Wikipedia: Video Game Crash of 1983 | The Brick That Saved Gaming

Homework Assignment 📝

Assignment: Singleton Implementation & Testing

Due: Next class
Submission: Video upload to D2L

Requirements:

  1. Implement Singleton<T> generic base class
  2. Implement GameManager using Singleton pattern
  3. Add StartGame(), PauseGame(), ResumeGame() functionality
  4. Create 5 test scenes
  5. Add TestGameManager script to each scene
  6. Record video showing:
    • Playing through all 5 scenes
    • Game Manager persisting
    • Pause/Resume working (P and R keys)
    • Scene transitions (N key)

Recording Your Test Video

Video Requirements

  • Length: 2-5 minutes
  • Show: Unity Editor + Game View
  • Demonstrate: All test cases working
  • Audio: Optional narration explaining what you're testing
  • Format: MP4, MOV, or AVI

Recording Tools

  • Windows: ShareX (instructor's choice!), Xbox Game Bar (Win + G), OBS Studio
  • Mac: QuickTime Screen Recording, OBS Studio
  • Linux: SimpleScreenRecorder, OBS Studio
  • Free: All these tools are free!

D2L Submission Instructions

How to Submit

  1. Log in to D2L course shell
  2. Navigate to Assignments → Singleton Pattern Implementation
  3. Upload your video file
  4. In the comments, include:
    • Your name
    • Any issues you encountered
    • What you learned
  5. Submit before deadline
File Size: If your video is too large for D2L, upload to YouTube (unlisted) and submit the link instead.

Grading Rubric (100 points)

Point Breakdown

25 pts: Singleton<T> base class correctly implemented
25 pts: GameManager inherits and uses Singleton properly
15 pts: StartGame(), PauseGame(), ResumeGame() work correctly
15 pts: 5 test scenes created and configured
10 pts: Instance persists across all scenes
10 pts: Video clearly demonstrates all functionality

Additional Resources

📚 Further Reading

  • Baron's Chapter 4: Complete Singleton implementation details
  • C# Docs: Static classes and members
  • Game Programming Patterns: Singleton Pattern
Office Hours: If you get stuck on the implementation, come see me! Don't wait until the last minute.

Questions & Discussion đŸ’Ŧ

Open Floor

Questions about:

  • The patterns roadmap?
  • When to use Singleton vs other patterns?
  • Implementation details?
  • Testing strategy?
  • Homework requirements?
  • Video recording/submission?

Ready to Build! 🚀

Today's Achievements:

Homework Due Next Class:

Singleton implementation + 5-scene test video

Upload to D2L

Your first design pattern implementation awaits! đŸŽ¯