View Format: Multi-Page Single Page

Simple Enemy Forge

Generate Complete Enemy Databases, Squads, Spawn Tables, and More in Minutes.

Squad Forge

Squad Forge groups enemies into reusable encounter configurations. Instead of spawning individual enemies one at a time, you define squads — named compositions of enemies with counts, level overrides, and custom properties — and reference them from Spawn Forge, Wave Forge, or your own game code.

Every squad links back to one or more Enemy Databases, so enemy codes are always validated against real data. You can attach dynamic properties (Categories, Flags, Numerics, Texts) to squads themselves — independent of the properties on individual enemies.

Open the wizard via Window › Simple Enemy Forge › Squad Forge Wizard.

Overview

Squad Forge is a 4-step wizard that walks you through the entire process:

Step 1 — Setup

Link one or more Enemy Databases and configure output naming. The wizard reads enemy codes from all linked databases so you can reference any enemy in your squads.

Step 2 — Definitions

Define custom properties for your squads — Categories, Flags, Numerics, and Texts. Export and import schemas for AI-assisted content generation.

Step 3 — Squads

Build squad compositions in a split-panel editor. Add enemy slots with codes, counts, and level overrides. Set dynamic property values per squad.

Step 4 — Generate

Generate the database ScriptableObject, type-safe enum, and a custom Inspector editor with search, sort, pagination, and bulk operations.

Step 1 — Setup

Link Enemy Databases

Squad Forge requires at least one Enemy Database to function. You add databases using a ReorderableList — drag to reorder, click + to add, - to remove. You can link multiple Enemy Databases; the wizard merges all enemy codes together using a first-DB-wins deduplication strategy (if two databases define the same code, the first one in the list takes priority).

The linked databases are used to:

  • Populate the Enemy Browser popup when assigning enemies to squad slots
  • Validate enemy codes in your squads
  • Provide code autocompletion in the slot editor

Output Configuration

Field Description Example
Database Name Display name for the generated asset My Squad Database
Class Prefix Prefix for generated C# class names My
Append Suffix Toggle to append a suffix between the prefix and the type name (toggle)
Suffix Text appended after the prefix when Append Suffix is enabled (e.g., "Squad" produces MySquadDatabase) Squad
Auto-Name from Database Toggle that auto-fills naming fields (Database Name, Class Prefix, Namespace) from the first linked Enemy Database name (toggle)
Namespace C# namespace for generated code MyGame.Data

Step 2 — Definitions

Define custom properties that apply to squads (not individual enemies). These are separate from and independent of the properties defined in Enemy Forge.

Property Types

Type Definition Fields Storage Example
Categories Label, entries[], allowMultiple int[] categoryValues Squad Type (Patrol, Ambush, Boss), Difficulty (Easy, Medium, Hard)
Flags Name, defaultValue bool[] flagValues Is Elite, Has Healer, Is Stealth
Numerics Name, isRange, isInteger, min/max float[] numericValues Challenge Rating, Recommended Level, Gold Bonus
Texts Name, lineCount string[] textValues Encounter Description, Tactical Notes

All four property sections are always visible in the wizard, even when no definitions exist. An empty section shows a "No X defined." placeholder.

Schema Export/Import

Four buttons at the top of the Definitions step let you exchange schemas with AI tools:

  • Export Full JSON — Complete schema with all definitions, squads, and linked enemy data. Ideal for giving AI full context.
  • Export Light JSON — Definitions only, no squad data. Smaller payload for when you just want AI to understand the structure.
  • Export Markdown — Human-readable documentation with tables, code blocks, and examples.
  • Import JSON — Import definitions and/or squads from AI-generated JSON. Presents a 3-choice dialog (Merge, Replace, Cancel) for both definitions and squads.

See AI Workflow for the complete export/import guide.

Step 3 — Squads

The main builder step uses a split-panel layout:

Left Panel — Squad List

  • Search — Filter squads by name or code
  • Sort — Sort alphabetically by name or code
  • Multi-select — Checkbox selection for bulk operations
  • ReorderableList — Drag to reorder, + to add, - to remove
  • Pagination — Toggle between Show All and paginated view (configurable items per page)

Right Panel — Squad Editor

Select a squad from the list to edit its details:

Identity

Field Description
Name Display name (e.g., "Goblin Patrol")
Code Unique identifier (e.g., "GOBLIN_PATROL"). Codes starting with "NEW_SQUAD" auto-generate from the name as you type.
Description Optional text description with scrollable TextArea

Slots

Each squad contains a ReorderableList of slots. A slot defines which enemy appears and in what quantity:

Field Description
Enemy Code Text field with a [...] browse button that opens an Enemy Browser popup. The browser shows all enemies from linked databases with search and filtering.
Count Min Minimum number of this enemy in the squad
Count Max Maximum number (same as min for a fixed count)
Level Optional level override (-1 uses the enemy's default level)

Dynamic Properties

Below the slots, a Properties section appears when at least one category, flag, or numeric is defined in Step 2. It shows Categories (as dropdowns), Flags (as toggles), and Numerics (as sliders) with values specific to this squad. Text properties are not rendered in the builder step.

Duplicating Squads

To duplicate squads, use the Duplicate button in the bulk operations toolbar in the left panel. Select one or more squads via the checkboxes, then click Duplicate to copy them (including all slots and property values) with modified names.

Step 4 — Generate

Generation uses a two-phase process to handle Unity's domain reload:

1 Phase 1 — Generate Scripts
Writes the C# source files, then calls AssetDatabase.Refresh() to trigger compilation and domain reload.
2 Phase 2 — Create Asset
After domain reload, an [InitializeOnLoad] handler fires via delayCall, reads squad data from a temporary JSON file, and creates the ScriptableObject asset.

Generated Files

File Description
{Prefix}SquadType.cs Enum with one entry per squad code (e.g., GOBLIN_PATROL, UNDEAD_HORDE)
{Prefix}SquadDatabase.cs ScriptableObject implementing ISimpleSquadDataSource with all squad data and metadata
Editor/{Prefix}SquadDatabaseEditor.cs Custom Inspector with split panel, search, sort, filter, multi-select, pagination, and bulk operations
{Prefix}SquadDatabase.asset The actual data asset containing all squads

Runtime Data Structures

SimpleSquadSlot

public struct SimpleSquadSlot { public string enemyCode; // Enemy code referencing the enemy database public int countMin; // Minimum spawn count public int countMax; // Maximum spawn count (same as min for fixed) public int level; // Level override (-1 = use enemy default) }

SimpleSquadGroup

public struct SimpleSquadGroup { public string code; // Unique identifier (e.g., "GOBLIN_PATROL") public string name; // Display name public string description; // Optional description public SimpleSquadSlot[] slots; // Enemy slots in this squad // Dynamic properties (aligned with database metadata) public int[] categoryValues; public bool[] flagValues; public float[] numericValues; public string[] textValues; }

Interface Reference — ISimpleSquadDataSource

All generated squad databases implement this interface:

Member Returns Description
SquadCount int Total number of squads in the database
GetAllSquads() SimpleSquadGroup[] Get all squad groups
GetSquadByCode(string code) SimpleSquadGroup? Get a squad by its code, or null if not found
GetSquadsContainingEnemy(string enemyCode) SimpleSquadGroup[] Get all squads that contain a specific enemy
GetCategoryLabels() string[] Get category labels
GetCategoryEntries(int categoryIndex) string[] Get entries for a specific category
GetFlagNames() string[] Get flag names
GetNumericNames() string[] Get numeric property names
GetTextNames() string[] Get text property names

Usage Example

// Access squad data at runtime ISimpleSquadDataSource squadDB = mySquadDatabase as ISimpleSquadDataSource; // Get a specific squad SimpleSquadGroup? patrol = squadDB.GetSquadByCode("GOBLIN_PATROL"); if (patrol.HasValue) { Debug.Log($"Squad: {patrol.Value.name} has {patrol.Value.slots.Length} slots"); foreach (var slot in patrol.Value.slots) { int count = Random.Range(slot.countMin, slot.countMax + 1); Debug.Log($" Spawn {count}x {slot.enemyCode}"); } } // Find all squads containing a specific enemy SimpleSquadGroup[] withGoblin = squadDB.GetSquadsContainingEnemy("GOBLIN_WARRIOR"); Debug.Log($"Found {withGoblin.Length} squads containing Goblin Warrior");

Tips

Design Varied Compositions

Create squads with different enemy mixes for the same encounter type. A "Forest Patrol" might have 3 variants: goblin-heavy, spider-heavy, and mixed. Spawn Forge or Wave Forge can then pick randomly between them.

Use Count Ranges

Set different countMin and countMax values to introduce natural variation. A squad slot with 2-4 goblins will feel different each time without needing multiple squad definitions.

Reference Enemy Codes Carefully

Squad slots reference enemies by code string. Use the [...] browse button to pick from your linked Enemy Databases rather than typing codes manually. If you rename an enemy code later, update it in your squads too.

AI-Generated Squads

Export your schema to an AI, describe your game's encounter design, and import dozens of squad compositions in seconds. The AI can reference any enemy code from your exported schema. See AI Workflow for details.