Enemy Handling System


Added an Enemy Handling System.

Overview

The Enemy System in this project manages the creation, registration, and removal of enemy entities. It comprises four core components:

  • EnemyManager: Central controller handling enemy registration, spawning, and cleanup.

  • EnemyFactory: Responsible for instantiating enemy prefabs based on type.

  • EnemySpawner: Handles delayed enemy spawning and spawn cancellation.

  • IEnemy (Interface): Abstract base class for all enemy types.

1. EnemyManager

Purpose

Acts as the central hub for managing all active enemies, coordinating their spawning, and handling cleanup when needed.

Fields

[SerializeField] public Transform enemiesHolder; 
[SerializeField] public GameObject guardEnemy; 
[SerializeField] public GameObject dogEnemy; 
public EnemySpawner enemySpawner; 
public EnemyFactory enemyFactory; 
private HashSet<IEnemy> activeEnemies = new HashSet<IEnemy>(); 

Key Methods

void Start()

  • Initializes EnemySpawner and EnemyFactory

  • Subscribes to game events for spawning enemies and handling results

void CreateSomeDummyEnemies()

  • Collects valid spawn cells from the maze

  • Schedules guard enemies to spawn on these cells

void OnResult()

  • Cancels all ongoing enemy spawns

  • Clears all active enemies from the scene

void RegisterEnemy(IEnemy enemy)

  • Adds an enemy to the active enemies list

void UnregisterEnemy(IEnemy enemy)

  • Removes an enemy from the active enemies list

void ClearAllEnemies()

  • Destroys all currently active enemies (note: can be updated to return to a pool)

2. EnemyFactory

Purpose

Instantiates enemy GameObjects based on their EnemyType.

Fields

public EnemyManager enemyManager; 

Constructor

public EnemyFactory(EnemyManager enemyManager) 

Key Method

IEnemy CreateEnemy(EnemyType enemyType, Vector3 position)

  • Uses a switch case to determine which prefab to instantiate

  • Initializes the enemy by calling InitializeEnemy()

  • Returns the initialized enemy object

3. EnemySpawner

Purpose

Handles scheduling and executing enemy spawns after a delay.

Fields

private EnemyManager enemyManager; 
private int spawnIdCounter = 0; 
private Dictionary<int, Coroutine> activeSpawns = new Dictionary<int, Coroutine>(); 

Constructor

public EnemySpawner(EnemyManager enemyManager) 

Key Methods

int ScheduleEnemySpawn(EnemyType type, Vector3 position, float delay)

  • Starts a coroutine that spawns the enemy after a delay

  • Stores the coroutine in a dictionary with a unique spawn ID

void CancelSpawn(int spawnId)

  • Stops the coroutine associated with the given spawn ID

void CancelAllSpawns()

  • Stops and clears all ongoing enemy spawn coroutines

IEnumerator SpawnEnemyWithDelay(int spawnId, EnemyType type, Vector3 position, float delay)

  • Waits for the specified delay and then calls SpawnEnemy()

void SpawnEnemy(EnemyType type, Vector3 position)

  • Delegates enemy creation to the factory

4. IEnemy (Abstract Base Class)

Purpose

Base class for defining behavior and common attributes of enemies.

Fields

[SerializeField] public EnemyData data; 
[SerializeField] public EnemyType type; 
[SerializeField] public float health; 
[SerializeField] public float damagePow; 
protected EnemyManager enemyManager; 

Key Methods

public virtual void InjectManager(EnemyManager manager)

Injects manager reference into the enemy.

protected void RegisterSelf()

Registers this enemy with the manager.

protected void UnregisterSelf()

Unregisters this enemy from the manager.

public abstract void InitializeEnemy(EnemyManager manager)

Must be implemented by subclasses to set initial properties.

public abstract void TakeDamage(float damage)

Must be implemented to define damage logic.

5. GuardEnemy (Concrete Class)

Purpose

Implements IEnemy for a guard-type enemy with health UI.

Fields

[SerializeField] Slider healthBar; 

Key Methods

public override void InjectManager(EnemyManager manager)

Passes manager to base method.

public override void InitializeEnemy(EnemyManager enemyManager)

  • Sets type, health, and damage from EnemyData

  • Injects and registers with manager

public override void TakeDamage(float damage)

  • Reduces health

  • Updates health bar UI

  • Destroys self when health <= 0 and unregisters from manager

if(health <= 0) 
{     
UnregisterSelf();     
Destroy(gameObject); // Replace with object pool return in future 
} 

Summary

  • Modular Design: The enemy system is split across dedicated classes for factory creation, timed spawning, centralized management, and behavior abstraction.

  • Reusable: Enemies follow a shared interface, enabling reusable and extensible code.

  • Event-Driven & Coroutine-Based: Ties into gameplay events and handles asynchronous spawning with coroutines.

  • Extensible: New enemy types can be easily added by implementing IEnemy.


Check out this for code implementation: Enemy

Files

MazeEscape.zip Play in browser
20 days ago

Leave a comment

Log in with itch.io to leave a comment.