Course contentsShow
← Unity Game Development
Lesson 243 of 8284. Prefabs and Data ManagementFree lesson

Building a Data-Driven Enemy Archetype System

Create diverse enemy behaviors by swapping out configuration data assets while using a single shared enemy controller script.

In this lesson, you will learn how to create diverse enemy behaviors by swapping out configuration data assets while using a single, shared enemy controller script.

Moving Beyond Hard-Coding

In early development, you might be tempted to create a unique script for every enemy type—like OrcController, GoblinController, and GhostController. As your game grows, this becomes a maintenance nightmare. A data-driven system solves this by separating the logic (the "how") from the stats (the "what").

The Strategy

Instead of hard-coding values, we create an EnemyData ScriptableObject. This asset acts as a container for properties like health, movementSpeed, and attackDamage. Our shared EnemyController script then holds a reference to an EnemyData asset.

Here is how the controller interacts with the data:

public class EnemyController : MonoBehaviour
{
    public EnemyData enemySettings; // The archetype asset

    void Start()
    {
        // Use the archetype data to initialize the enemy
        float health = enemySettings.maxHealth;
        float speed = enemySettings.moveSpeed;
        Debug.Log("Initialized enemy with speed: " + speed);
    }
}

Implementing the Archetype Workflow

  1. Define the Data: Create a ScriptableObject script called EnemyData containing all the variables that differentiate your enemies.
  2. Create Assets: In your Project window, right-click and create unique instances of this asset for each archetype (e.g., "BossData", "GruntData", "ScoutData").
  3. Configure Prefabs: You can now create a single Enemy prefab. To create a new enemy type, simply drag a different EnemyData asset into the enemySettings slot of your prefab's inspector.

By using this approach, you don't need to write new code to create a "Tank" enemy or a "Speedster." You simply tweak the numbers in a ScriptableObject asset, and the shared EnemyController automatically adapts its behavior. This makes your project modular, easier to balance, and significantly faster to iterate upon.

Key Takeaway: By using ScriptableObjects to store configuration data, you can transform a single, generic script into dozens of unique enemy archetypes just by swapping asset references.