β οΈ Real Impact: Spawning 100 bullets per second = 100 Instantiate() calls
+ 100 Destroy() calls = major performance hit!
Understanding Garbage Collection
What Happens When You Instantiate/Destroy
1. Instantiate()
β’ Allocates memory on the heap
β’ Creates GameObject, components, and scripts
β’ Registers in Unity's scene hierarchy
β’ Cost: Expensive!
2. Destroy()
β’ Marks object for deletion
β’ Leaves memory as "garbage"
β’ Doesn't immediately free memory
β’ Cost: Creates garbage!
3. Garbage Collection (GC)
β’ Unity pauses your game periodically
β’ Scans for unused memory
β’ Frees garbage back to system
β’ Cost: FRAME RATE STUTTER!
What is the Object Pool Pattern?
Object Pool Pattern
A creational pattern that manages a set of reusable objects,
handing them out when needed and reclaiming them when done,
instead of creating and destroying objects repeatedly.
β Key Concept
Recycle instead of recreate! Create objects once,
disable them when not in use, re-enable when needed again.
In Simple Terms: Like a library - books (objects) are checked out,
used, returned, and checked out again by someone else!
using UnityEngine;
namespace Chapter.ObjectPool
{
public classDrone : MonoBehaviour
{
public float speed = 5f;
public float maxHeight = 10f;
public float wobbleAmount = 2f;
// Called when drone is spawned from poolpublic voidOnSpawn()
{
gameObject.SetActive(true);
Debug.Log("[Drone] Spawned and activated");
}
// Called when drone is returned to poolpublic voidOnDespawn()
{
gameObject.SetActive(false);
Debug.Log("[Drone] Despawned and deactivated");
}
voidUpdate()
{
// Simple upward movement with wobblefloat wobble = Mathf.Sin(Time.time * wobbleAmount);
transform.Translate(Vector3.up * speed * Time.deltaTime);
transform.Translate(Vector3.right * wobble * Time.deltaTime);
// Release back to pool when reaching max heightif (transform.position.y > maxHeight)
{
DroneSpawner.Instance.ReleaseDrone(this);
}
}
}
}
Implementation Step 2: Spawner Setup
using UnityEngine;
using UnityEngine.Pool;
namespace Chapter.ObjectPool
{
public classDroneSpawner : MonoBehaviour
{
// Singleton accesspublic static DroneSpawner Instance { get; private set; }
// Pool configurationpublic Drone dronePrefab;
public int defaultCapacity = 10;
public int maxPoolSize = 50;
public bool collectionCheck = true;
// The object poolprivate ObjectPool<Drone> _pool;
voidAwake()
{
Instance = this;
// Create the pool with callbacks
_pool = new ObjectPool<Drone>(
createFunc: CreateDrone,
actionOnGet: OnGetDrone,
actionOnRelease: OnReleaseDrone,
actionOnDestroy: OnDestroyDrone,
collectionCheck: collectionCheck,
defaultCapacity: defaultCapacity,
maxSize: maxPoolSize
);
}
}
}
Implementation Step 3: Pool Callbacks
// Continuing DroneSpawner class...// Called when pool needs to create a new droneprivate Drone CreateDrone()
{
Drone drone = Instantiate(dronePrefab);
drone.gameObject.SetActive(false);
Debug.Log("[Pool] Created new drone");
return drone;
}
// Called when drone is taken from poolprivate voidOnGetDrone(Drone drone)
{
drone.OnSpawn();
Debug.Log("[Pool] Drone retrieved from pool");
}
// Called when drone is returned to poolprivate voidOnReleaseDrone(Drone drone)
{
drone.OnDespawn();
Debug.Log("[Pool] Drone returned to pool");
}
// Called when pool is cleared (optional cleanup)private voidOnDestroyDrone(Drone drone)
{
Destroy(drone.gameObject);
Debug.Log("[Pool] Drone destroyed");
}
Implementation Step 4: Public API
// Continuing DroneSpawner class...// Spawn a drone at specified positionpublic Drone SpawnDrone(Vector3 position)
{
Drone drone = _pool.Get();
drone.transform.position = position;
return drone;
}
// Release drone back to poolpublic voidReleaseDrone(Drone drone)
{
_pool.Release(drone);
}
// Get pool statisticspublic intGetActiveCount()
{
return _pool.CountActive;
}
public intGetInactiveCount()
{
return _pool.CountInactive;
}
voidOnDestroy()
{
// Clean up pool when spawner is destroyed
_pool.Clear();
}
Implementation Step 5: Test Client
using UnityEngine;
namespace Chapter.ObjectPool
{
public classTestPool : MonoBehaviour
{
public float spawnInterval = 0.5f;
public float spawnRange = 5f;
private float _nextSpawnTime;
voidUpdate()
{
// Spawn drones periodicallyif (Time.time > _nextSpawnTime)
{
// Random spawn position
Vector3 randomPos = new Vector3(
Random.Range(-spawnRange, spawnRange),
0f,
Random.Range(-spawnRange, spawnRange)
);
DroneSpawner.Instance.SpawnDrone(randomPos);
_nextSpawnTime = Time.time + spawnInterval;
}
}
voidOnGUI()
{
// Display pool statistics
GUILayout.Label($"Active Drones: {DroneSpawner.Instance.GetActiveCount()}");
GUILayout.Label($"Pooled Drones: {DroneSpawner.Instance.GetInactiveCount()}");
}
}
}
Critical: Object Reset Logic
β οΈ Always Reset Object State!
When objects are reused, they carry over their previous state.
You MUST reset them to clean initial conditions!
public voidOnSpawn()
{
gameObject.SetActive(true);
// CRITICAL: Reset all state!
transform.rotation = Quaternion.identity; // Reset rotation
GetComponent<Rigidbody>()?.ResetVelocity(); // Stop movement
health = maxHealth; // Reset health
currentState = DroneState.Idle; // Reset state machine// Reset any timers, counters, flags, etc.
elapsed = 0f;
isAggro = false;
}
Common Bug: Forgetting to reset velocity on Rigidbody objects,
causing "ghost momentum" on respawn!
Testing the Object Pool
Test Setup Steps
Create new Unity scene
Create Drone prefab (Cube with Drone script)
Create empty GameObject "DroneSpawner"
Attach DroneSpawner script, assign drone prefab
Create empty GameObject "TestPool"
Attach TestPool script
Run and watch drones spawn/recycle!
What to Observe
Drones spawn every 0.5 seconds
Drones rise to max height, then disappear
Watch console logs: "Created" only appears once per unique drone!
GUI shows active vs pooled count
Performance Comparison
Without Pooling
~15ms
GC spike every 2 seconds
Frame drops visible
With Pooling
~0.1ms
No GC spikes
Smooth 60 FPS
Performance Metrics (100 drones/sec)
Memory Allocations: 150x reduction
GC Frequency: 95% reduction
Frame Time Consistency: 10x improvement
Mobile Battery Life: ~20% longer
Hands-On Implementation π»
30-Minute Implementation Challenge
Implement the Object Pool Pattern:
Create Drone MonoBehaviour with OnSpawn/OnDespawn
Create DroneSpawner with ObjectPool<Drone>
Implement all four pool callbacks
Create TestPool spawning script
Add GUI to display pool statistics
Test and verify objects are recycled (check console logs)
Success Metric: Console should show "Created new drone" only 10-15 times
even after spawning 100+ drones!
Pro Tip: Use Unity Profiler to measure actual peak concurrent objects in gameplay!
What to Pool in Games
π« Projectiles
Bullets, arrows, missiles, lasers
Why: Spawned frequently, short-lived
πΎ Enemies
Minions, drones, zombies
Why: Wave-based spawning
π₯ VFX
Explosions, impacts, trails
Why: Particle systems are expensive
π΅ Audio Sources
Sound effect players
Why: Many sounds play simultaneously
π Pickups
Coins, health, power-ups
Why: Spawn/despawn continuously
π UI Elements
Damage numbers, notifications
Why: Instantiate/Destroy is slow
Advanced: Pool Warm-Up
// Pre-populate pool at startup for zero initial lagvoidStart()
{
// Create pool
_pool = new ObjectPool<Drone>(
createFunc: CreateDrone,
actionOnGet: OnGetDrone,
actionOnRelease: OnReleaseDrone,
actionOnDestroy: OnDestroyDrone,
defaultCapacity: 20
);
// WARM-UP: Pre-create objectsvar tempList = new List<Drone>();
for (int i = 0; i < 20; i++)
{
tempList.Add(_pool.Get());
}
// Return all to pool immediatelyforeach (var drone in tempList)
{
_pool.Release(drone);
}
Debug.Log("[Pool] Warmed up with 20 drones");
}
Benefit: Eliminates first-spawn lag. Crucial for tight gameplay!
Homework Assignment π
Assignment: Drone Pool with Performance Testing
Due: Next class Submission: Unity project + video to D2L
Part 1: Core Implementation (50 points)
Implement Drone class with OnSpawn/OnDespawn + custom reset logic
Implement DroneSpawner with Unity ObjectPool<Drone>
Add all four pool callbacks with debug logs
Create TestPool that spawns 2 drones/second
Add GUI showing active/inactive pool counts
Homework Assignment (Continued)
Part 2: Performance Comparison (50 points)
Create Two Scenes:
Scene A: WITHOUT pooling (Instantiate/Destroy)
Scene B: WITH pooling (ObjectPool)
Both scenes spawn 100 drones over 10 seconds
Record performance metrics:
Open Unity Profiler (Window β Analysis β Profiler)
Record FPS average
Record GC.Alloc count
Take screenshots of Profiler CPU usage
Document findings: Which scene performs better? By how much?
Bonus (+10 points):
Implement pool warm-up that pre-creates 20 drones at Start()
Video Submission Guidelines
Recording Checklist (3-5 minutes)
Show Code: Briefly show Drone and DroneSpawner classes
Show Scene Setup: Hierarchy and Inspector settings