DunGen - Procedural Dungeon Generation

Looks like prefab prop nesting was broken when I made some optimizations to prop spawning in 2.16. I’ve just pushed a new build (2.17.4) to the Asset Store (EDIT: It’s up now)

2 Likes

I tested the fix and problem is gone. Thank you for fast issue solving.

1 Like

Hi, is there a way to make sure that all tiles are connected or to have no dead ends?

Unfortunately, there’s no way to guarantee that all your doorways are used, but there are a few things that can be done to help with dead end tiles.

Branch Cap Tiles

You can set specific tiles to be used as branch caps, though there’s still no guarantee that the branch caps will be used every time since the branch might not have enough room to grow to its full length.

Branch cap tiles can be set in the ‘Archetype’ asset as shown:

With the branch cap type set to ‘Instead Of’, DunGen will always try to use the specified tiles on the end of a branch instead of the usual tiles.

Branch Pruning

If you have some tiles that are okay to spawn at the end of a branch, you can add a tag to them to mark them as such. Go to ‘Window > DunGen > Tags’ to create a new tag (it could be named ‘Valid Branch Cap’ for example).

Tags can be assigned in the Tile component attached to your tile prefabs.

If you also assign this tag to the ‘Branch Prune Tags’ list in the dungeon flow asset (using the default branch prune mode of ‘All Tags Missing’), DunGen will systematically remove any tiles that appear at the end of a branch if they don’t have that tag. If none of the tiles in the branch have the tag, it will remove the whole branch, so be sure to tag as many tiles as possible.

You can also do the opposite by using ‘Any Tag Present’ and specifically tagging tiles that don’t work as a branch cap (e.g. a corridor tile). DunGen will prune any cap tiles that have the tag. This might be the better workflow if most of your tiles are fine to use at the end of branches.

This technique pairs well with the branch cap tiles mentioned above to ensure that only tiles that work well at the end of a branch will be used.

Hello!

Is there an event or a way to find out if the first/starting tile has been created?

My dungens take a while to finish sometimes, and until they do, the player is left in limbo waiting to be moved. So I’m wondering if there is a OnFirstTileCreated event I could listen to and move them then.

Thanks!

Sorry for the late reply.

Unfortunately, there isn’t an event for this at the moment because the entire tile instantiation step (that converts the proxy dungeon layout into actual geometry) is done synchronously.

The next best thing is to hook into the generation status event and move your player when the generator reaches the Post-Processing step, since that is the next one after tile instantiation (see below). The post-processing step is usually very quick though so there’s not likely to be much improvement over just checking for completion instead.

private void OnEnable()
{
	RuntimeDungeon.Generator.OnGenerationStatusChanged += OnDungeonGenerationStatusChanged;
}

private void OnDungeonGenerationStatusChanged(DungeonGenerator generator, GenerationStatus status)
{
	if (status != GenerationStatus.PostProcessing)
		return;

	// TODO: Move the player character
}

The plan is to change this for the next version (2.18) so there are optional pauses while instantiating tiles so the game can continue to run in the meantime. I’ve added a note for myself to also implement a callback event for when a tile is spawned. Unfortunately, I’m not sure when the next version will be ready at the moment.

Do you know if there is a way to create portals with SECTR inside a tile itself? That would allow to have proper portals vis inside big tiles inside the procedural dungeon. I made it work ONLY if the tile is the starting one. I guess you could add an option for tiles like “MultiPortal” and assigning the entry portal and exit one when placing the tiles adjancent to the “MultiPortal” one in the creation process.

Thank you, I appreciate the response.

Would there be any issue with me adding a script to the Starting tile that moves the player to it as soon as the Starting tile is instantiated?

I have another small issue with using DunGen and SECTR. For the most part, it works perfectly, but I have an oddly shaped tile where it culls the entire tile in one specific area.

The red lines are the Doors. When the player enters the green area, everything is culled until they get to the next door and the next tile is shown. Is there a way around this or is this tile just not shaped the right way for SECTR?

It’s not something I’d really considered before, but it should be possible though it will require some custom programming.

From what testing I’ve done, it seems easy enough to set up sectors inside a tile and link them together with portals. The biggest problem is that these ‘sub sectors’ won’t be visible unless you’re standing inside them, and since portals are placed automatically by the SECTR adapter you’d need some custom script to handle re-connecting them.

I think the best approach would be to make a script that can be attached to your doorway components and contains a reference to the SECTR Sector you want the doorway portal to connect to. You could then modify the SECTR adapter script to look through all doorway components that have your new script and reconnect them to the sector in your script, then just delete the whole-tile sector that the adapter created.

Moving the player like that should be fine, I can’t see any issue with doing it that way.

Regarding your other issue, the only thing I can think of is that the SECTR Sector doesn’t cover the green area in your image. You should be able to see where the sector is by running the game in the editor, then switching to the scene view - sectors will be displayed as a cyan box. By default it should cover the whole tile though.

However, there is another issue if both of those doorways belong to the same tile. DunGen uses one axis-aligned bounding box per-tile for collision detection, so it doesn’t currently support doorways on concave edges. If the bounds come up to the doorway on the left, the right doorway would never be used as any tile attached to it would be inside the bounds of this tile. If the bounds only come up to the doorway on the right, the leftmost doorway would be outside the bounds and could potentially overlap other tiles.

Hi @Aegon-Games! I’m trying to use the new-ish feature where I can use multiple entrances and exits, but when I try it makes it so some of my doors are never used. Here’s the example:

The E’s are the two possible entrances, the X’s are the two possible exits (i always want the user to have to traverse the hallway to exit so its not just a short turn). The two smaller doors on the sides are a different socket type reserved for branches.

If I populate the tile’s possible exits and entrances as shown in the diagram above, the branch doors are NEVER used. If I don’t assign any entrances or exits, or only assign one each, they get used just fine. Not really sure what’s happening

It’s not very clear so it’s worth mentioning here that exits also apply to branches leaving the tile, so your two side doors won’t be used until both the designated exit doorways have been exhausted. If the ‘Branch Count’ property in your archetype is set to a maximum of 1, DunGen will never be able to use the side doors as the tile requires at least one branch to use up the remaining exit door.

Beyond that, I can’t think of any reason the side doors wouldn’t be used.

I think I fixed it, had something to do with the tile bounds; I think i cleaned up some hard to see objects that were part of the prefab that were extending the automatic bounds further than I wanted.

Side note: I’m deploying on meta quest 3, and the enormous CPU spike at generation time, even with generate asynchronously enabled, causes my device to crash 3/4 times. Is there any steps I can take to try and alleviate that?

EDIT: weirdly enough, disabling asynchronous generation stops the crash :man_shrugging:

DunGen 2.18 (Beta 1) - Download

Created 05 December 2024
Be sure to backup your project before updating to a beta version of DunGen.

Features

  • Doorway connector and blocker prefabs can now optionally use position & rotation offsets to correctly align the prefabs

Enhancements

  • Tile instantiation is now also asynchronous if ‘Generate Asynchronously’ is enabled in the generator settings
  • PauseBetweenRooms is automatically disabled outside of the editor so it won’t affect the performance of builds

I’m not familiar with meta quest development so I don’t really know why it might be crashing when using asynchronous generation - I’ve never seen that happen before on PC. My first thought was that maybe the coroutines were generating a lot more garbage, but after profiling, that doesn’t seem to be the case.

It might be worth trying to generate asynchronously with a lower ‘Max Frame Time’ (from the RuntimeDungeon component). By default it’s set to 50 milliseconds, but you could try setting it to something like 10 so DunGen will do less work before yielding control for a frame.

I doubt this will help at the moment, but I’ve just pushed the first beta build for DunGen 2.18 which I’m planning on making mostly performance & usability improvements. It’s in an early state right now but one thing I have done is to make the actual tile instantiation asynchronous if ‘Generate Asynchronously’ is enabled.

Is there a way to generate a single tile at a specific door during runtime when a condition is fulfilled(ex a player presses a button)?

There’s no built-in way to change the dungeon after it’s generated.

If you wanted to do it manually, there’s a helper function UnityUtil.PositionObjectBySocket() that can help to put a tile into the correct position based on the doorways specified, but it doesn’t handle doorway blocker and connector objects.

Got it, thanks!

I have a few more questions (or maybe enhancement requests? :innocent:)

  1. What would be to best way to allow a tile to repeat, but disallow immediate, and put a limit on the number of times it can appear?

  2. When placing a fixed tile node on the flow like the mini boss room in the simple example, those tiles never get branches. I get why (bc the flow is linear) but it’d be nice if there was some way to try to force a branch or number of branches on them, via the inspector on the node maybe?

Hi.

In the documentation is a link to a sample code to check the status.

I downloaded the file/code but I can’t attach it to the object that has the RuntimeDungeon component because it is throwing an error. I’m not a very experienced coder, so I’m kinda lost about what could be the problem. This is the error:

CS0123: No overload for ‘OnDungeonStatusSomething’ matches delegate ‘GenerationStatusDelegate’

Any help will be appreciated. Thanks

Unfortunately, I think these are both going to have to be future features. I can’t think of a way to achieve either right now without custom code.

The second point is one that I already have on my list for the future, though I’m not 100% sure how I’m going to end up implementing it yet.

Your first point seems like a good fit for a generic constraint system that I’ve also got on my list, but this one is probably not going to be something I can do in the short term because of how complex and far reaching the system will need to be.

If you’re up for making some changes to the DunGen source code, your first point could be achieved by adjusting the AddTile() function in DungeonGenerator.cs around line 740 where the chanceEntries variable is set. This list contains all the tile prefabs that will be considered when choosing which tile to spawn next. You can remove tiles from the list if too many of that particular tile have already been placed.