View Format: Multi-Page Single Page

Simple Enemy Forge

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

Simple Attribute Forge Integration

Simple Enemy Forge has optional integration with Simple Attribute Forge (SAF), sold separately. When both packages are installed in the same project, the Enemy Forge automatically detects SAF and unlocks modifier references on enemies. No manual configuration is required — just import both packages and the features appear.

Completely optional. Simple Enemy Forge works perfectly on its own. The SAF integration adds modifier reference capabilities, but all core functionality (enemies, squads, spawn tables, scaling, waves, behaviors, factions, schema export, custom editors) works without SAF installed. You can add or remove SAF at any time with zero compilation errors.
Modifier-only integration. Unlike Simple Item Forge’s SAF integration (which includes attribute requirements, stat bonuses, and modifiers), Simple Enemy Forge’s SAF integration is lighter. Enemies only hold modifier references — ScriptableObject references to SAF modifier assets that represent buffs, debuffs, damage-over-time, or other effects an enemy can apply. Enemy stats are handled entirely through the dynamic numerics system (HP, ATK, DEF, etc.), so attribute requirements and stat bonuses are not needed.

Features Enabled by SAF

When SAF is detected, one additional capability appears in the Enemy Forge wizard and generated editors:

Modifier References

Each enemy can hold drag-and-drop references to SAF Modifier ScriptableObjects for effects like poison, burn, slow, stun, or buff auras. Stored as ScriptableObject[] on the generated database. Useful for defining what effects an enemy can apply to the player or other entities during combat.

Where SAF Features Appear

Location What Changes
Enemy Forge — Step 1 (Setup) A “Simple Attribute Forge Integration” section appears, confirming SAF is detected and modifier support is active.
Enemy Forge — Step 3 (Enemies) Each enemy gets a Modifiers section with a ReorderableList of ScriptableObject references. Drag modifier assets directly from your project to assign them.
Schema Export Exported schemas include modifier names (as strings) for each enemy. AI can reference modifier names, but Unity asset references cannot be set via JSON import — modifiers must be assigned manually via drag-and-drop.
Generated Custom Editors The generated Inspector editor shows a Modifiers section for each enemy, with ObjectField pickers filtered to SAF modifier assets when SAF is installed.

Detection Lifecycle

SAF detection is fully automatic and bidirectional. An [InitializeOnLoad] detector runs every time Unity performs a domain reload (after compilation, script changes, or package imports). It uses reflection only — no hard assembly references — so it compiles cleanly whether SAF is present or not.

Installing SAF

1 Import the SAF package
Import Simple Attribute Forge into your project (Asset Store or .unitypackage). Unity detects new scripts and triggers compilation.
2 Domain reload → Detector fires
After compilation, Unity performs a domain reload. The [InitializeOnLoad] attribute on AttributeForgeDetector causes it to run automatically. It calls Type.GetType("SimpleForgeFramework.SimpleModifierAssetBase, SimpleModifierSystem.Runtime") to probe for SAF’s modifier types.
3 Define symbol added
SAF types are found. The detector adds SIMPLE_ATTRIBUTE_FORGE to Player Settings → Scripting Define Symbols. It also populates SAFBridge with the resolved ModifierAssetBaseType and builds a GetModifierMetadata delegate via reflection.
4 Recompilation → SAF features appear
The new define triggers another compilation. Editor code gated behind SAFBridge.IsAvailable checks now activates. The Modifiers section appears in the Enemy Forge wizard, and generated editors gain modifier ObjectFields.

Removing SAF

1 Delete the SAF package
Remove Simple Attribute Forge from your project. Unity detects the missing scripts and triggers compilation.
2 Domain reload → Detector fires again
The same [InitializeOnLoad] detector runs. This time, Type.GetType() returns null — SAF types are no longer present.
3 Define symbol removed
The detector removes SIMPLE_ATTRIBUTE_FORGE from the scripting defines. It also clears all SAFBridge properties (sets ModifierAssetBaseType and GetModifierMetadata to null).
4 Recompilation → Zero errors
The removed define causes another compilation. All SAF-gated editor code is excluded. The Modifiers sections disappear from the wizard. No compilation errors occur because modifiers are stored as plain ScriptableObject[] in runtime types (see below).

The SAFBridge Pattern

Simple Enemy Forge never has a hard assembly reference to Simple Attribute Forge. Instead, all editor code accesses SAF through a static bridge class:

Component Role
AttributeForgeDetector [InitializeOnLoad] class that probes for SAF types via Type.GetType(). If found, populates SAFBridge with resolved types and a reflection-built metadata delegate. If not found, clears everything. Also manages the SIMPLE_ATTRIBUTE_FORGE define symbol.
SAFBridge Static class with properties: ModifierAssetBaseType (System.Type), GetModifierMetadata (delegate that extracts name, description, tag, duration, effects from a modifier SO), and IsAvailable (bool). All wizard and editor code checks SAFBridge.IsAvailable before showing modifier UI.

This pattern means:

  • No using SimpleForgeFramework; statements in the main editor code
  • No assembly definition references to SAF assemblies
  • No conditional assemblies that might fail to recompile
  • Clean compilation in both directions (install and remove)
Why not conditional assemblies? A separate assembly with defineConstraints and hard using references to SAF would seem simpler, but it creates a dangerous edge case: if SAF is deleted while the define symbol still lingers, the conditional assembly tries to compile with missing references, causing errors that prevent the [InitializeOnLoad] detector from running — leaving the project stuck. The reflection-based SAFBridge pattern avoids this entirely.

Runtime vs. Editor Behavior

SAF integration is split into two layers: unconditional runtime types that always compile, and conditional editor code that only activates when SAF is present.

Always Compiled (Unconditional)

The SimpleEnemyDefinition struct in the runtime namespace always includes:

Field Type Purpose
modifiers ScriptableObject[] Array of modifier references (SAF modifier assets when available)

Because modifiers are stored as ScriptableObject[] (not a SAF-specific type), the generated database class always compiles — the field exists whether SAF is installed or not. This is what makes the install/remove cycle error-free.

Conditional (Editor Only)

The following editor features are gated behind SAFBridge.IsAvailable runtime checks and only activate when SAF is installed:

  • The “Simple Attribute Forge Integration” section in Enemy Forge Step 1
  • Modifier ReorderableList UI in Enemy Forge Step 3
  • Modifier data sections in schema export (Full JSON, Light JSON, Markdown)
  • Modifier ObjectField sections in generated custom editors (uses runtime Type.GetType() for ObjectField type filtering — auto-adapts when SAF is installed/uninstalled without regeneration)

When SAF is removed, these sections simply disappear. The wizard reverts to its base feature set with no visible errors or broken UI.

Generated Database Behavior

Understanding how generated databases behave across SAF install/remove cycles:

Generated With SAF Installed

When you generate an Enemy Database while SAF is available and modifiers are assigned:

  • Each enemy’s modifiers array holds references to modifier .asset files
  • The generated custom editor shows modifier ObjectFields filtered to SAF modifier assets

After Removing SAF

  • The generated database still compilesScriptableObject[] is an unconditional Unity type
  • Existing references are preserved in the .asset file — Unity serializes ScriptableObject references regardless of the asset’s type
  • The custom editor hides the Modifiers section — you won’t see modifiers in the Inspector, but the data is still there in the serialized asset
  • Modifier references become null if the modifier .asset files were removed along with SAF

Regenerating Without SAF

If you open the Enemy Forge wizard and regenerate without SAF installed:

  • The wizard has no modifier UI, so no modifiers can be assigned
  • Generated enemies will have empty modifiers arrays
  • The previous .asset data is overwritten with the new (empty) data
  • If you want to preserve modifier data, do not regenerate after removing SAF
Safe round-trip: Install SAF → generate with modifiers → remove SAF → everything compiles → reinstall SAF → data still in the asset. As long as you don’t regenerate while SAF is absent, your modifier data survives the round-trip.

Troubleshooting

SAF features not appearing after import

  • Check installation — Ensure Simple Attribute Forge is imported in the same project (not a different project or a Package Manager reference to a missing path)
  • Check the define symbol — Open Player Settings → Scripting Define Symbols and verify SIMPLE_ATTRIBUTE_FORGE is listed. If not, the detector may not have run yet.
  • Force a recompile — Try Assets → Reimport All or make a trivial edit to any script to trigger compilation and a domain reload.
  • Check the Console — If SAF itself has compilation errors, the detector cannot find its types. Fix any SAF errors first.

SAF features not disappearing after removal

  • Check the define symbol — If SIMPLE_ATTRIBUTE_FORGE is still in Scripting Define Symbols after deleting SAF, remove it manually and recompile.
  • Force a domain reload — The detector runs on domain reload. If Unity didn’t trigger one, reimport a script or restart Unity.

Modifier references lost after regeneration

  • Modifier fields store Unity object references to .asset files. These references survive regeneration as long as the modifier assets still exist at the same paths.
  • If modifier assets were moved or deleted, re-assign them in the generated Inspector editor.
  • Modifier references cannot be set via JSON import — they must be assigned manually via drag-and-drop in the wizard or the generated editor.

Compilation errors after removing SAF

This should never happen if Simple Enemy Forge is the only package using SAF. If you see errors:

  • Check that SIMPLE_ATTRIBUTE_FORGE was removed from Scripting Define Symbols
  • Check for other packages or custom scripts that may have hard references to SAF types
  • Ensure you deleted the entire SAF package, not just parts of it (partial deletion can leave broken assembly definitions)