Learn the difference between Strategy and State patterns
Implement enemy drone behaviors using Strategy pattern
Create runtime-swappable attack maneuvers
Recognize when to use Strategy vs. other patterns
Explore alternative solutions using Unity's animation system
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.
๐ฏ Enemy Drone Design
Core Concept
Flying robotic enemies that attack the player with predictable, automated behaviors.
Characteristics:
Weapon: Front-facing laser beam (45ยฐ angle)
Intelligence: No AI - pure algorithmic movement
Difficulty: Easy alone, challenging in formations
Attack Patterns: Three distinct maneuvers
Design Philosophy: Like Goombas in Super Mario Bros - simple,
predictable, but dangerous when positioned strategically.
โ๏ธ Three Attack Maneuvers
1. Bobbing Maneuver
Rapid vertical movement (up and down)
Continuous laser fire
Hard to predict vertical position
2. Weaving Maneuver
Rapid horizontal movement (side to side)
Limited to track rail distance
Forces player to time their pass
3. Fallback Maneuver
Moves backward while shooting
Can match player's bike speed
Limited duration before stopping
๐ Understanding Strategy Pattern
Core Concept
Define a family of algorithms, encapsulate each one, and make them interchangeable at runtime.
Key Benefits:
Select behavior at runtime
No need to know object's internal state
Algorithms encapsulated in separate classes
Easy to add new strategies without modifying context
Runtime selection: User chooses which strategy to use
๐๏ธ Strategy Pattern Structure
Key Participants:
Context: Uses strategy objects
In our case: Drone class
Strategy Interface: Common interface for all strategies
In our case: IManeuverBehaviour
Concrete Strategies: Specific implementations
BoppingManeuver
WeavingManeuver
FallbackManeuver
Pattern Type: Behavioral - focuses on how objects interact and
distribute responsibility.
โ๏ธ Strategy vs State Pattern
Aspect
Strategy Pattern
State Pattern
Intent
Select algorithm at runtime
Change behavior when state changes
Selection
Client decides which strategy
Object changes its own state
Awareness
Strategies don't know about each other
States often trigger transitions
Use Case
Different ways to do the same thing
Different behaviors in different states
For our drones: We use Strategy because behavior is assigned at
spawn time, not based on internal state changes.
โ Benefits of Strategy Pattern
Encapsulation:
Each algorithm in its own class
Avoid long conditional statements
Cleaner, more organized code
Runtime Flexibility:
Swap algorithms dynamically
No need to restart or rebuild
Responsive to gameplay conditions
Open/Closed Principle:
Open for extension (new strategies)
Closed for modification (existing code)
Testing:
Test each strategy independently
Mock strategies for unit tests
โ ๏ธ Potential Drawbacks
Client Awareness:
Client must know about all strategies
Must understand which to select
Increased coupling to strategy types
Pattern Confusion:
Strategy and State look similar structurally
Team members may misunderstand intent
Requires clear documentation
Class Proliferation:
More classes to manage
Can be overkill for simple cases
Mitigation: Regular team discussions about architecture choices
and pattern usage conventions.
๐ค When to Use Strategy Pattern
Use Strategy When:
โ Multiple variants of same behavior needed
โ Want to assign behavior at runtime
โ Internal state doesn't dictate behavior changes
โ Need to accomplish specific task based on runtime criteria
Use State/FSM Instead When:
โ Behavior changes based on internal state
โ Need state transitions and history
โ Object is inherently stateful (e.g., player character)
Other Use Cases for Strategy:
Encryption algorithms (platform-dependent)
Pathfinding algorithms (A*, Dijkstra, etc.)
Spell behaviors in fantasy games
Difficulty level implementations
๐ป Implementation: Strategy Interface
๐ File Structure Note - PRODUCTION CODE
Create a new file: Assets/Scripts/Patterns/Strategy/IManeuverBehaviour.cs
This interface defines the contract that all drone maneuver strategies must implement. โ ๏ธ This code goes into your Unity project for Blade Racer.
publicinterface IManeuverBehaviour
{
// Execute maneuver on given dronevoidManeuver(Drone drone);
}
Key Points:
Single method that all strategies must implement
Accepts Drone parameter - important!
Strategies can access drone's public properties
Simple, focused interface
Why pass Drone? Strategies need access to drone properties like
speed, maxHeight, weavingDistance, etc.
๐ป Drone Class - Context (1/2)
๐ File Structure Note - PRODUCTION CODE
Modify existing file: Assets/Scripts/Enemies/Drone.cs
Add the fields and methods below to your Object Pool drone โ do not create a new file. โ ๏ธ This code goes into your Unity project for Blade Racer.
โ ๏ธ Don't Create a Duplicate Drone Class
You already have Assets/Scripts/Enemies/Drone.cs from the Object Pool lecture.
Unity compiles all scripts into one assembly, so a second class Drone anywhere in the
project will cause a compile error. Instead, extend the drone you already built:
add the laser ray fields, weavingDistance, fallbackDistance,
ApplyStrategy(), and swap Update() to draw the debug ray.
Your existing OnSpawn() and OnDespawn() pool methods stay untouched.
Drone accepts any strategy that implements IManeuverBehaviour
Drone doesn't know how the strategy works internally
Drone only knows the interface (Maneuver method)
Strategy gets full access to drone via this parameter
Behavior can be changed at runtime by passing different strategy
Separation of Concerns: Drone handles core properties and
weapon; strategies handle movement patterns.
๐ป BoppingManeuver - Concrete Strategy
๐ File Structure Note - PRODUCTION CODE
Create a new file: Assets/Scripts/Patterns/Strategy/BoppingManeuver.cs
First concrete strategy implementation - makes drones bob up and down. โ ๏ธ This code goes into your Unity project for Blade Racer.
Add this animation loop to the Execute() coroutine in the previous slide.
while (true) // Infinite loop!
{
time = 0;
Vector3 start = drone.transform.position;
Vector3 end = (isReverse) ? startPosition : endPosition;
// Lerp from start to end over timewhile (time < speed)
{
drone.transform.position =
Vector3.Lerp(start, end, time / speed);
time += Time.deltaTime;
yield returnnull;
}
yield returnnewWaitForSeconds(1); // Pause at top/bottom
isReverse = !isReverse; // Reverse direction
}
}
}
๐ป WeavingManeuver - Concrete Strategy
๐ File Structure Note - PRODUCTION CODE
Create a new file: Assets/Scripts/Patterns/Strategy/WeavingManeuver.cs
Second concrete strategy - makes drones weave side to side. โ ๏ธ This code goes into your Unity project for Blade Racer.
Add this animation loop to the Weave() coroutine in the previous slide.
while (true)
{
time = 0;
Vector3 start = drone.transform.position;
Vector3 end = (isReverse) ? startPosition : endPosition;
while (time < speed)
{
drone.transform.position =
Vector3.Lerp(start, end, time / speed);
time += Time.deltaTime;
yield returnnull;
}
yield returnnewWaitForSeconds(1);
isReverse = !isReverse;
}
}
}
Note: Very similar to BoppingManeuver, but moves on X axis instead of Y
๐ป FallbackManeuver - Concrete Strategy
๐ File Structure Note - PRODUCTION CODE
Create a new file: Assets/Scripts/Patterns/Strategy/FallbackManeuver.cs
Third concrete strategy - makes drones retreat backward. โ ๏ธ This code goes into your Unity project for Blade Racer.
Problems: 150+ line Drone class, hard to test, hard to maintain,
violates Single Responsibility Principle
๐ป TestPanel - Drone Spawning (1/2)
๐ Evolving TestPanel.cs
Modify existing file: Assets/Scripts/Testing/TestPanel.cs
Add drone spawning directly to TestPanel โ no separate ClientStrategy file needed. โ ๏ธ This code goes into your Unity project for Blade Racer.
// Add at the top of TestPanel.cs (with other usings)using System.Collections.Generic;
// Add to TestPanel fieldspublic GameObject dronePrefab; // Drag your Drone prefab here in the Inspectorprivate bool _strategyExpanded = true;
private GameObject _drone;
private List<IManeuverBehaviour> _components =
new List<IManeuverBehaviour>();
// Add to TestPanel โ spawns a drone with a random strategyprivate voidSpawnDrone()
{
_drone = Instantiate(dronePrefab);
_drone.transform.position = Random.insideUnitSphere * 10;
ApplyRandomStrategies();
}
๐ป TestPanel - Drone Spawning (2/2)
๐ Continuing TestPanel.cs
Add ApplyRandomStrategies() to TestPanel โ called by SpawnDrone() from the previous slide.
// Add to TestPanelprivate voidApplyRandomStrategies()
{
// Add all three strategies as components
_components.Add(
_drone.AddComponent<WeavingManeuver>());
_components.Add(
_drone.AddComponent<BoppingManeuver>());
_components.Add(
_drone.AddComponent<FallbackManeuver>());
// Pick one randomlyint index = Random.Range(0, _components.Count);
// Apply the selected strategy
_drone.GetComponent<Drone>().
ApplyStrategy(_components[index]);
}
๐ฎ TestPanel - GUI Section & Keyboard Shortcut
๐ Continuing TestPanel.cs
Add the keyboard shortcut to Update() and the collapsible GUI section to your TestPanel.cs.
// Add to Update() - Strategy Pattern shortcut// G = Generate/Spawn droneif (Input.GetKeyDown(KeyCode.G))
SpawnDrone();
โ Behavior is algorithmic (pathfinding, damage calculation)
โ Not purely visual/animated
โ Need to combine multiple systems
โ Behavior includes complex logic beyond animation
Use Unity Animator When:
โ Primarily visual animation
โ Need smooth transitions
โ Animation created by artists
โ State-based with transitions
Hybrid Approach:
// Strategy determines WHAT to dopublicclass SmartAttackStrategy : IManeuverBehaviour
{
publicvoidManeuver(Drone drone)
{
// Calculate best attack based on player position// Then trigger appropriate animation
drone.animator.SetTrigger("ExecuteCalculatedAttack");
}
}
๐ Beyond Drone Maneuvers
Real-World Game Applications:
Save File Encryption:
saveManager.SetEncryptionStrategy(
platform == PC ? newAES256() : newSimpleXOR()
);
Difficulty Settings:
enemy.SetBehaviorStrategy(
difficulty == Hard ? newAggressiveAI() : newPassiveAI()
);
[Test]
publicvoidBoppingManeuver_MovesVertically()
{
// Arrangevar drone = newGameObject().AddComponent();
drone.maxHeight = 10f;
var strategy = drone.gameObject.AddComponent();
float startY = drone.transform.position.y;
// Act
strategy.Maneuver(drone);
yield returnnewWaitForSeconds(2f); // Let coroutine run
// Assert
Assert.AreNotEqual(startY, drone.transform.position.y);
Assert.LessOrEqual(drone.transform.position.y, drone.maxHeight);
}
[Test]
publicvoidDrone_CanSwitchStrategies()
{
// Arrangevar drone = newGameObject().AddComponent();
var bop = drone.gameObject.AddComponent();
var weave = drone.gameObject.AddComponent();
// Act
drone.ApplyStrategy(bop);
yield returnnewWaitForSeconds(1f);
drone.ApplyStrategy(weave); // Switch!
// Assert - Should not throw, should execute smoothly
Assert.IsNotNull(drone);
}
๐ซ Common Mistakes to Avoid
Forgetting to Stop Previous Coroutine:
// BAD - old strategy still running!
drone.ApplyStrategy(newStrategy);
// GOOD - stop previous firstStopAllCoroutines();
drone.ApplyStrategy(newStrategy);
Common Theme: Runtime selection of behavior based on context
๐ Summary
What We Learned:
โ Strategy pattern encapsulates algorithm families in separate classes
โ Enables runtime behavior selection without state dependency
โ Perfect for enemy drones with predictable, swappable maneuvers
โ Similar to State pattern but with different intent
โ Alternative: Unity Animator for pure animation cases
Key Takeaways:
Context class uses strategies through interface
Each strategy is independent and testable
Easy to extend with new behaviors
Consider Unity's native systems for animation
Strategy pattern shines for algorithmic behaviors
Gaming History Moment ๐น๏ธ
Console Wars: Sega vs Nintendo (1989-1995)
In the early 1990s, Sega and Nintendo employed radically different competitive strategies. Nintendo focused on quality control, family-friendly games, and their established Mario brand. Sega chose an aggressive, edgy strategy - "Genesis does what Nintendon't!" They targeted teenagers, emphasized speed and attitude with Sonic, and pursued sports licenses Nintendo ignored.
Both companies could swap strategies mid-battle. Sega released Sonic Spinball (family-friendly pinball) when their edgy approach plateaued. Nintendo countered with Mortal Kombat (with blood code!) abandoning their clean image temporarily. Each company's "context" (market position) stayed the same, but they swapped "strategies" (marketing approaches) based on what worked.
Connection to Strategy Pattern
The Console Wars demonstrate the Strategy Pattern perfectly! Both companies (contexts) could employ different competitive strategies (algorithms) without changing their core identity. Just as our Drone context switches between FallbackManeuver, WeavingManeuver, and BoppingManeuver strategies at runtime, Sega and Nintendo switched between "Family Friendly," "Edgy Teen," and "Sports Focus" strategies based on market conditions. The strategy changes, but the company stays the same!