Skip to content

Advanced Features: Avoiding Collisions with Scene Objects

By default, DunGen only checks for collisions between the Tiles it is currently placing within the same generation process. It isn't inherently aware of other objects you might have manually placed in your scene (like important landmarks, puzzle elements, or structural pillars). This can lead to generated dungeons overlapping or intersecting with these crucial scene elements.

DunGen provides two primary methods, implemented via code, to tell the generator about additional areas it should avoid colliding with.


Method 1: Additional Bounding Boxes

This is the simpler approach for defining basic "keep-out" zones. You provide DunGen with a list of pre-defined Bounds objects representing volumes in world space that generated Tiles should not overlap.

  • Concept: Define one or more invisible, axis-aligned rectangular boxes around your important scene objects. DunGen will treat these boxes as obstacles during its collision checks.
  • Implementation:

    1. You need access to the DungeonGenerator instance used by your Runtime Dungeon component. Typically, you get this in Awake or Start in a script attached to the same GameObject as the Runtime Dungeon.
    2. A List<Bounds> can be accessed via the DungeonGenerator class (DungeonGenerator.Settings.CollisionSettings.AdditionalCollisionBounds)
    3. Create new Bounds objects (defining their center and size) that encompass the areas you want to protect.
    4. Add these Bounds objects to the AdditionalCollisionBounds list before DunGen starts generating.
  • Example Code:

    using UnityEngine;
    using DunGen;
    
    public class SceneCollisionSetup : MonoBehaviour
    {
        // Assign the RuntimeDungeon component in the inspector
        public RuntimeDungeon RuntimeDungeon;
    
        // Define a custom volume (in world space) to be treated as a collision area by the generator
        public Bounds BlockingVolume = new Bounds(new Vector3(10, 0, 0), new Vector3(20, 10, 20));
    
    
        private void Awake()
        {
            if(RuntimeDungeon == null)
            {
                Debug.LogError("RuntimeDungeon or its Generator not found!");
                return;
            }
    
            var collisionSettings = RuntimeDungeon.Generator.Settings.CollisionSettings;
            collisionSettings.AdditionalCollisionBounds.Add(BlockingVolume);
    
            Debug.Log("Added custom collision bounds to DunGen Generator.");
        }
    }
    
  • Limitations: This method only works with axis-aligned bounding boxes. It might protect a larger area than necessary for complex or rotated objects.


Method 2: Custom Collision Function (Predicate)

For more complex collision logic or checking against specific objects without relying on simple bounding boxes, you can provide DunGen with a custom function (a predicate).

  • Concept: You define a function that DunGen calls every time it considers placing a Tile. This function receives information about the potential Tile's bounds and returns true if the placement should be prevented (collision detected) or false if the placement is allowed.
  • Implementation:

    1. Access the DungeonGenerator instance and get its CollisionSettings property as described in Method 1.
    2. The DungeonCollisionSettings class has a public property: AdditionalCollisionsPredicate. This expects a delegate of type AdditionalCollisionsDelegate.
    3. Create a function in your script that matches the required signature:
      bool YourFunctionName(
          Bounds potentialTileBounds,
          bool isTileCollidingWithDungeon)
      
    4. Assign your function to the AdditionalCollisionsPredicate property before generation starts.
  • Delegate Signature Explained:

    • Bounds potentialTileBounds: The world-space AABB of the Tile that DunGen is considering placing.
    • bool isTileCollidingWithDungeon: A boolean indicating if DunGen's internal checks have already detected a collision between this potential Tile and other Tiles within the currently generating dungeon. This is useful to avoid redundant checks or to allow your custom logic to override DunGen's internal check if needed (though usually you'll want to respect it).
    • Return Value:
      • true: Collision detected by your custom logic. Prevent placement.
      • false: No collision detected by your custom logic. Allow placement.
  • Example Code:

    using UnityEngine;
    using DunGen;
    
    public class SceneCollisionSetupCustom : MonoBehaviour
    {
        // Assign in the inspector
        public RuntimeDungeon RuntimeDungeon;
        // Define which layers to check against in the Inspector
        public LayerMask CollisionCheckLayer;
    
    
    
        private void Awake()
        {
            if (RuntimeDungeon == null)
            {
                Debug.LogError("RuntimeDungeon should be set in the inspector");
                return;
            }
    
            // Assign our custom collision predicate
            var collisionSettings = RuntimeDungeon.Generator.Settings.CollisionSettings;
            collisionSettings.AdditionalCollisionsPredicate = ShouldTilePlacementBeBlocked;
    
            Debug.Log("Assigned custom collision predicate to DunGen Generator.");
    
        }
    
        private void OnDestroy()
        {
            if (RuntimeDungeon == null)
                return;
    
            // Clean up by removing our custom collision predicate
            var collisionSettings = RuntimeDungeon.Generator.Settings.CollisionSettings;
            collisionSettings.AdditionalCollisionsPredicate = null;
    
            Debug.Log("Removed custom collision predicate from DunGen Generator.");
        }
    
        // Function matching the AdditionalCollisionsDelegate signature
        private bool ShouldTilePlacementBeBlocked(Bounds potentialTileBounds, bool isTileCollidingWithDungeon)
        {
            // 1. Respect DunGen's internal collision check first
            if (isTileCollidingWithDungeon)
                return true; // Already colliding with another generated tile, definitely block.
    
            // 2. Perform your custom check (e.g., check for overlap with specific layers)
            Collider[] overlaps = Physics.OverlapBox(
                potentialTileBounds.center,
                potentialTileBounds.extents, // OverlapBox uses extents (half-size)
                Quaternion.identity,         // AABBs are not rotated
                CollisionCheckLayer          // Check only against specified layers
            );
    
            // 3. Decide based on the custom check
            if (overlaps.Length > 0)
                return true; // Found an object on the collision layer within the bounds, block placement.
    
            // 4. No collision found by DunGen or custom logic
            return false; // Allow placement.
        }
    }
    
  • Flexibility: This method is much more powerful. You can implement complex checks: query specific objects, use Physics.OverlapBox, Physics.CheckSphere, check tags, ignore triggers, etc.


Choosing a Method

  • Use Additional Bounding Boxes for simple, rectangular keep-out zones around non-rotated objects. It's easier to set up.
  • Use the Custom Collision Function for more precise checks, handling complex shapes, checking against specific layers or tags, or implementing any custom collision logic your project requires.

Remember to apply these settings in Awake or Start in a script that runs before the Runtime Dungeon component attempts to generate the dungeon (e.g., if generating on start).