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:
- You need access to the
DungeonGeneratorinstance used by yourRuntime Dungeoncomponent. Typically, you get this inAwakeorStartin a script attached to the same GameObject as theRuntime Dungeon. - A
List<Bounds>can be accessed via theDungeonGeneratorclass (DungeonGenerator.Settings.CollisionSettings.AdditionalCollisionBounds) - Create new
Boundsobjects (defining theircenterandsize) that encompass the areas you want to protect. - Add these
Boundsobjects to theAdditionalCollisionBoundslist before DunGen starts generating.
- You need access to the
-
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
trueif the placement should be prevented (collision detected) orfalseif the placement is allowed. -
Implementation:
- Access the
DungeonGeneratorinstance and get itsCollisionSettingsproperty as described in Method 1. - The
DungeonCollisionSettingsclass has a public property:AdditionalCollisionsPredicate. This expects a delegate of typeAdditionalCollisionsDelegate. - Create a function in your script that matches the required signature:
- Assign your function to the
AdditionalCollisionsPredicateproperty before generation starts.
- Access the
-
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).