Skip to content

Advanced Features: Custom Post-Processing Steps

DunGen's generation process involves several stages: creating the main path, adding branches, placing props, handling the lock & key system, etc. Sometimes, you need to inject your own custom logic during this process, specifically after the main dungeon layout (Dungeon data structure) exists but before generation is fully marked as complete.

This is useful for:

  • Integrating third-party systems (like pathfinding baking or custom culling setups) that need the final level geometry.
  • Running complex analysis or modification routines on the generated Dungeon data.
  • Implementing custom prop placement logic that depends on the overall dungeon structure.
  • Performing tasks that need to happen after DunGen's built-in post-processing (like lock/key placement) but before the final GenerationStatus.Complete event fires.

DunGen offers two ways to add your custom post-processing logic:

  1. Registering Steps via Code: Use the RegisterPostProcessStep method on the DungeonGenerator for fine-grained control.
  2. Creating Custom Adapters: Derive a component from BaseAdapter for a more component-based approach, often used for integrations.

Method 1: Registering Steps via Code (RegisterPostProcessStep)

This method allows you to dynamically register a C# method to be called during the post-processing phase.

How it Works:

  1. Get a reference to your DungeonGenerator instance.
  2. Call the generator.RegisterPostProcessStep() method, providing your callback method and configuration options.
  3. DunGen will execute your callback method at the appropriate time during its post-processing phase.

The Method Signature:

void RegisterPostProcessStep(Action<DungeonGenerator> postProcessCallback, int priority, PostProcessPhase phase);
  • Action<DungeonGenerator> postProcessCallback: This is your custom method (or lambda expression) that will be executed. It receives the DungeonGenerator instance as an argument, allowing you to access the generated dungeon data via generator.CurrentDungeon.
  • int priority: Determines the execution order within a specific phase. Higher priority numbers execute first. Steps with the same priority have an undefined execution order relative to each other. DunGen's built-in steps (like lock/key placement) also have priorities.
  • PostProcessPhase phase: An enum specifying when your step should run relative to DunGen's internal post-processing:
    • PostProcessPhase.BeforeBuiltIn: Your step runs before DunGen handles its standard post-processing (Locks, Keys, Props, etc).
    • PostProcessPhase.AfterBuiltIn: Your step runs after DunGen handles its standard post-processing.

Example:

public class MyCustomPostProcessor : MonoBehaviour
{
    // Assign your Runtime Dungeon component in the inspector
    public RuntimeDungeon RuntimeDungeon;

    private void Start()
    {
        if (RuntimeDungeon == null)
            return;

        // Register our custom method to run AFTER DunGen's built-in steps, with priority 0
        RuntimeDungeon.Generator.RegisterPostProcessStep(MyCustomPostProcessLogic, 0, PostProcessPhase.AfterBuiltIn);
    }

    private void OnDestroy()
    {
        if (RuntimeDungeon == null)
            return;

        // Unregister our custom method
        RuntimeDungeon.Generator.UnregisterPostProcessStep(MyCustomPostProcessLogic);
    }

    // This is the method that gets called by DunGen
    private void MyCustomPostProcessLogic(DungeonGenerator generator)
    {
        Debug.Log("Running custom post-process step!");

        // Access the generated dungeon data
        Dungeon dungeon = generator.CurrentDungeon;

        // Perform your custom logic here
        Debug.Log($"Dungeon has {dungeon.AllTiles.Count} tiles.");
    }
}

Use Cases: Ideal for one-off post-processing tasks defined in specific scripts, or when you need precise control over execution order relative to DunGen's built-in steps.


Method 2: Creating Custom Adapters (BaseAdapter)

This approach is more component-oriented and is the standard way DunGen integrates systems like Pathfinding and Culling. You create a new script that inherits from DunGen.Adapters.BaseAdapter.

How it Works:

  1. Create a new C# script.
  2. Make it inherit from DunGen.Adapters.BaseAdapter.
  3. Override the abstract Run(DungeonGenerator generator) method. This is where your custom logic goes.
  4. Attach this new component script to the same GameObject that has the RuntimeDungeon component.
  5. DunGen will automatically find all BaseAdapter components on that GameObject and execute their Run methods during the post-processing phase.

Adapter Properties:

  • Priority (Inspector Field): Inherited from BaseAdapter. This integer value controls the execution order of all post-processing steps within the same phase. Higher priority adapters run first.

Execution Phase

Adapters derived from BaseAdapter run after DunGen's built-in post-processing steps, similar to PostProcessPhase.AfterBuiltIn.

Example:

using UnityEngine;
using DunGen;
using DunGen.Adapters;

// Attach this component to the same GameObject as RuntimeDungeon
public class MyCustomAdapter : BaseAdapter
{
    protected override void Run(DungeonGenerator generator)
    {
        Debug.Log($"Running MyCustomAdapter (Priority: {Priority})");

        Dungeon dungeon = generator.CurrentDungeon;
        if (dungeon == null)
        {
            Debug.LogError("Dungeon data is null in custom adapter!", this);
            return;
        }

        // --- Add custom logic here ---
        Debug.Log($"Adapter processing dungeon with {dungeon.AllTiles.Count} tiles.");
        // Example: Find all objects with a specific tag and activate them
        // foreach(var tile in dungeon.AllTiles) { ... }
    }
}

Use Cases: Excellent for creating reusable integration components (like the built-in pathfinding/culling adapters), especially when the logic might need configuration via Inspector fields on the component itself. Easier to manage as self-contained units.


Choosing the Right Method

  • RegisterPostProcessStep:
    • Use when you need very fine control over execution order relative to DunGen's internal steps (BeforeBuiltIn vs. AfterBuiltIn).
    • Use when the logic is part of a script that isn't naturally attached to the RuntimeDungeon GameObject.
    • Use when you need to dynamically add/remove steps based on runtime conditions.
  • BaseAdapter:
    • Use for creating self-contained, reusable integration components (preferred for integrations like pathfinding, culling, etc.).
    • Use when you want to configure the step via the Inspector (add public fields to your adapter).
    • Generally simpler setup if you just need logic to run after the main generation and built-in steps. Ordering is primarily relative to other adapters.

Custom post-processing provides a vital hook for tailoring the generated dungeon and integrating it fully with your game systems.