Dungeon Generator

In October of 2014 I created my Randomized Dungeon System. After release it turned out to be flawed with bugs. Recently I discovered the level instance feature of UE4 and decided to try it again from scratch. I came up with a new generator which still uses tiles compared to other generators which are only able to use walls and floors on a fixed grid. Since I’ve gained a lot of experience in the meantime, this new version should be much cleaner, more stable and more professional. It is still made completely with blueprints.

You can use it in commercial and non-commercial projects and are not required to give credit to me.

>>Download<<](DungeonGenerator4.18.rar - Google Drive)
(for 4.18)
(Requires the free plugin LE Extended Standard Library
)
[HR][/HR]
Features:

  • Each tile is a separate level. It can contain anything a regular level can.
  • Performance friendly by having an automated system of hierarchical instanced static meshes implemented.
  • Connections can go in all directions (not limited to a grid).
  • TileCondition and LayoutModifier classes exist to modify the layout during the generation process (create child classes and assign them to the tiles)
  • Tiles can have limited amounts so unique or rare tiles only spawn a couple of times at most.
  • Tiles will only spawn where they don’t intersect with “WorldStatic” collisions.
  • Actors exist to help with the tile setup process.

Limitations:

  • No seeds/random streams implemented right now.
  • Only one generator can exist in a level.
  • Spawning the levels after layouting the tiles is performance intense and takes a while.
  • No replication for multiplayer.

[HR][/HR]
The generator works in two phases: layouting and spawning. First the layout is set up by spawning DungeonTile actors in the level and connecting them. Afterwards the DungeonTile actors spawn their assigned levels before getting destroyed as they are only placeholders.

There are three examples included in the project. The first one is a dungeon made of hallways. It shows that there can be multiple types of connections (“narrow” and “wide” in this case) and that actors placed inside level tiles and navigation works fine.

The second example consists of hexagonal tiles as you see them in many strategy games. They use the connections “G” and “W” (Ground and Water) at the edges to generate natural looking landmasses (compared to tiles which are either completely ground or water). It’s also best for showing the difference between the “From Center”-mode turned on and off. When turned on, the generator will add the next tile to the one that is closest to the level’s origin, leaving no gaps in this example.

The third example has a train track raging in all directions with twists and turns. The fact that connections can be rotated and therefore generate twisted layouts is what this example is supposed to display.

[HR][/HR]
Tutorial

At this point I have no video detailing the exact procedure of using this generator, but here’s a quick rundown:

  1. Create levels which you want to use as tiles.

  2. Place TileConnection actors in it at the points where it should connect to another tile (red arrow towards next tile). Enter a keyword in their properties to indicate the type of connection it uses.

  3. Place a DungeonTileHelper actor in it (it will automatically move itself to the level’s origin) and fill out the TileData information (the connection information is automatically gathered from the TileConnection actors).

  4. Rightclick the TileData structure variable from the DungeonTileHelper and copy it.

  5. Create a new DataTable asset (Miscellaneous > Data Table) for the “TileEntry” structure. Create an entry and paste the copied TileData into it.

  6. Repeat this for all the tiles you need.

  7. Create a new DataTable asset for the “ConnectionMatch” structure. Add one entry for each type of connection your tiles have and add the types of connections it can connect to to the array.
    20180717-19_15_16Greenshot.jpg

  8. Create a new level and place the DungeonGenerator actor in it.

  9. Setup the Generator’s properties (read the tooltips!).

  10. Place at least one DungeonTile actor in the scene and enter the name of a row of the data table you created to turn it into the associated tile.

  11. Start playing or simulating the level.

  12. Add all levels used for tiles to the packaging settings in the project settings. Otherwise they will not be packaged and missing from the final game.

If you did everything correctly, a dungeon/level should be generated. If not, read the tooltips of each property, study the examples and ask questions in this thread. I’ll try to create a video later but that might take a few weeks as my job is demanding and I only have the energy to work on something during weekends.

Hi @DasMatze!
I justed spent the last 2 days examinating all the options for maze/dungeon generation!
Your implementation seems to be the best choice for my needs!

Do you what modifications would have to be done to get a seed generation? Are you currently implementing this option?
If not, could you point me toward the good direction in order to do it. I would gladly share it if I succeed of course!

Once I have some fancy screenshot, i will post the result I achieved using your system.

Thanks again!! :slight_smile:

In a newer version I successfully implemented seeds. I planned to release it as soon as I found a way to eliminate the need of copying and pasting settings.

Thanks to 4.20, there is an option to fill data tables with blueprints from an CSV string. The problem is the data contains rotation values which need to be entered in another format (quaternion) and I have no idea how to convert pitch, yaw and roll to x,y,z and w.

If you want to add seeds yourself, open the DungeonGenerator blueprint, add a variable of the type “Random Stream”, in the “Setup Generator” function, set the value of the variable to a random integer in case the value is 0 (optional, so you still can have random generation)(see image), replace all “random integer in range”-nodes with “random integer in range from stream”-nodes and hook up the variable.

20181108-17_05_11Greenshot.jpg

Ok, that’s great news! I will try and implement the random seed, but I’m really looking forward to your new version!
Here is what I got from just one day messing around with the system:

I still don’t know how to put some rules to prevent too many rooms to be spawned in the same area or too many paths but I will search more; I really like the fact that the connection points can be anywhere in the sublevels; You can have dungeon going up and down one several floors.

I don’t think I will work on my version anytime soon.

Not just that, they can also be at any angle! The rigidity is what bugged me most about other generators.

That’s what the tile condition and layout modifier actor classes are for. Let’s say you wanted to prevent straight corridors from spawning directly next to each other like in this area:

First you create a child class of the “tile condition” class and assign it to your “straight” tile in the settings of the dungeon tile helper. Inside the new sub class, you set up some box collision components to the left and the right of the straight corridor which overlap WorldStatic objects:

Override the “Check Condition” function of the parent class and set it up like this:

This function checks each box for overlapping tiles and returns false once any of those tiles is a straight corridor, otherwise it will return true.

This Tile Condition actor will get spawned during the layout generation process. Once a tile has passed the collision check, the tile condition is placed with the same transforms as the tile itself and the Check Condition function determines whether the tile will be kept or whether another one will be tried.

Once the generator is done with placing new tiles, Layout Modifier actors will be spawned at each tile (if any are assigned) and their “Modify Layout” function will be executed. They can be used the same way as tile conditions, like checking whether an X-crossing has a dead end on one of it’s connection points so it can destroy the dead end and turn the X-crossing into a T-crossing. Or a Straight corridor if there are two dead ends opposite of each other.

Afterwards the Layout Modifier actors will be deleted and the levels assigned to the classes will be spawned in the world.

I hope this little example made clear how the layout can be influenced during and after generating a dungeon. Let me know, if you need any more help.

Also, I kept this article in my reading list: Removing&nbsp;Quaternions from 3D Engines
They seem to explain quaternion in a new way that make them really to understand.

I just found a good way to do it using the connection system!
You can create a connection RoomToPath and a connection Path; you then set the RoomToPath to be able to connect only with Path; Path can connect with RoomToPath and Path! Works like a charm!! I did the same for my crossing tile, they have a connection named Crossing which can connect only with paths!

1 Like

Hey, I love this generator and I love that you made it free, however, I’m having trouble with generation and I’m not sure what to do. The level generates and maybe 1/4 of it is normal but the rest is all overlapping. The lighting is also weird (my lights only effect the ceiling). I was wondering what I was doing wrong. I can post screenshots if you want.

Yes, a screenshot would be helpful.

I actually made a video because I think it shows it off better. Correct generation is shown 20 seconds in. https://www.youtube.com/watch?v=PLdIv81lht0

Thanks for the video. You set up the collision meshes correctly, right? Could it be your dead-end tiles which reach into other tiles? They are not tested for collisions. They should either be a flat wall or reaching forward into the hallway.

1 Like

The dead ends are flat walls. It’s still not working. How are you supposed to create the collision? I have basic block versions of each of my corridors that are the same dimensions.

I’ve also noticed that the majority of the overlapping tiles are corners, t-crossings, and x-crossings.

I looked at your project and see that your collision meshes use the “Use complex collision as simple” setting. This cannot be used since the generator uses these models to detect overlapping tiles. To do that, the collision meshes need to consist of convex primitives which means you need to use the “Default” setting and add collision primitives.

There are multiple ways to add collisions: https://docs.unrealengine.com/en-US/…ttingCollision

The best way to add collisions are custom collisions: https://docs.unrealengine.com/en-US/…shes#collision

Make sure the collisions do not reach to the edge of the tile otherwise a tiny bit might overlap with the neighbor tile and will be rejected.

Was there ever a video created for this I am having a hard time figuring out how to make this work correctly.

Looks interesting, good job!

might i ask how i would go about adding a start and end room and maybe specific rooms that are required to be added so that i might add specific goals

Adding a start room is easy, as you need to place at least one tile in the main map. The generator itself doesn’t act like a starting point. The start room should have probability set to 0 to not be spawned anymore.

For the end room, create a child class of the TileCondition class and overwrite the “Check Condition” function. Add this to check whether the end room and dungeon generator (which you can place at the start room) are at least 5000 units apart (so it won’t spawn right next to the start):


Then assign this child class to the tile and set amount to 1, so it will only get successfully spawned once.

Other unique rooms should also have a limited amount. To check whether all necessary rooms have been spawned, you can create a child class of the LayoutModifier blueprint and overwrite the “Modify Layout” function. In there you can fetch all DungeonTile actors, go through them and look for the necessary rooms. If they are not available, call the “Restart” event in the DungeonGenerator.

There is no way implemented to check whether one connection is connected with another connection, so checking whether a keycard can be obtained before facing the door to use this keycard on, needs to be done using your own blueprints.

2 Likes

Hi DasMatze, first of all - thank you very much for the script! With the help of your script, I want to generate a residential building. And I have a question - it is possible to make the transitions not Narrow + Narrow and Wide + Wide, but a Special transition in which you could choose which types of transitions can be contacted. Sorry for my English. I think it will be clearer in the picture.

it seems that the restart event on the dungeon generator doesn’t work properly it resets the generated level but doesn’t begin anew since the connections on the “start tile” was deleted during the first generation…

and is there a way to make it so that the tiles line up sometimes they are pushed a bit to the side relative to the tile they are connected with…

Are we allowed to use this in projects we plan to sell?