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.
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
Import Simple Attribute Forge into your project (Asset Store or .unitypackage). Unity detects new scripts and triggers compilation.
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.
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.
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
Remove Simple Attribute Forge from your project. Unity detects the missing scripts and triggers compilation.
The same
[InitializeOnLoad] detector runs. This time,
Type.GetType() returns null — SAF types are no longer present.
The detector removes
SIMPLE_ATTRIBUTE_FORGE from the scripting defines. It also clears
all SAFBridge properties (sets ModifierAssetBaseType and
GetModifierMetadata to null).
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)
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
modifiersarray holds references to modifier.assetfiles - The generated custom editor shows modifier ObjectFields filtered to SAF modifier assets
After Removing SAF
- The generated database still compiles —
ScriptableObject[]is an unconditional Unity type - Existing references are preserved in the
.assetfile — 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
.assetfiles 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
.assetdata is overwritten with the new (empty) data - If you want to preserve modifier data, do not regenerate after removing SAF
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 Symbolsand verifySIMPLE_ATTRIBUTE_FORGEis listed. If not, the detector may not have run yet. - Force a recompile — Try
Assets → Reimport Allor 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_FORGEis still inScripting Define Symbolsafter 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
.assetfiles. 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_FORGEwas 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)