Announcement

Collapse
No announcement yet.

Dungeon Generator

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

    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.

    (for 4.18)
    (Requires the free plugin LE Extended Standard Library
    )


    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.


    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.

    Click image for larger version  Name:	HighresScreenshot00001.jpg Views:	1 Size:	99.3 KB ID:	1502970Click image for larger version  Name:	HighresScreenshot00002.jpg Views:	1 Size:	217.1 KB ID:	1502971

    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.

    Click image for larger version  Name:	HighresScreenshot00005.jpg Views:	1 Size:	161.9 KB ID:	1502972Click image for larger version  Name:	HighresScreenshot00006.jpg Views:	1 Size:	207.1 KB ID:	1502973

    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.

    Click image for larger version  Name:	HighresScreenshot00003.jpg Views:	1 Size:	196.6 KB ID:	1502974Click image for larger version  Name:	HighresScreenshot00004.jpg Views:	1 Size:	188.9 KB ID:	1502975

    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.
    Click image for larger version  Name:	20180716-20_24_16Greenshot.jpg Views:	1 Size:	95.9 KB ID:	1502976

    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.
    Click image for larger version  Name:	20180717-19_13_54Greenshot.jpg Views:	1 Size:	122.3 KB ID:	1502977

    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.
    Click image for larger version  Name:	20180717-19_14_39Greenshot.jpg Views:	1 Size:	101.4 KB ID:	1502978

    5. Create a new DataTable asset (Miscellaneous > Data Table) for the "TileEntry" structure. Create an entry and paste the copied TileData into it.
    Click image for larger version  Name:	20180717-19_14_51Greenshot.jpg Views:	1 Size:	106.4 KB ID:	1502979

    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.
    Click image for larger version  Name:	20180717-19_15_16Greenshot.jpg Views:	1 Size:	14.5 KB ID:	1502980

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

    9. Setup the Generator's properties (read the tooltips!).
    Click image for larger version  Name:	20180717-19_15_55Greenshot.jpg Views:	1 Size:	140.8 KB ID:	1502981

    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.
    Click image for larger version  Name:	20180717-19_17_16Greenshot.jpg Views:	1 Size:	147.5 KB ID:	1502982

    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.
    Click image for larger version  Name:	20180717-21_39_00Greenshot.jpg Views:	1 Size:	86.0 KB ID:	1503032

    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.
    Last edited by DasMatze; 07-17-2018, 03:52 PM.

    #2
    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!!

    Comment


      #3
      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.

      Click image for larger version  Name:	20181108-17_05_11Greenshot.jpg Views:	1 Size:	62.4 KB ID:	1549316
      Last edited by DasMatze; 11-08-2018, 12:07 PM.

      Comment


        #4
        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.
        Attached Files

        Comment


          #5
          Originally posted by thebenjiman View Post
          I will try and implement the random seed, but I'm really looking forward to your new version!
          I don't think I will work on my version anytime soon.

          Originally posted by thebenjiman View Post
          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.
          Not just that, they can also be at any angle! The rigidity is what bugged me most about other generators.

          Originally posted by thebenjiman View Post
          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
          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:
          Click image for larger version  Name:	1.jpg Views:	1 Size:	12.3 KB ID:	1549446

          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:
          Click image for larger version  Name:	2.jpg Views:	1 Size:	187.0 KB ID:	1549448

          Override the "Check Condition" function of the parent class and set it up like this:
          Click image for larger version  Name:	3.jpg Views:	1 Size:	131.6 KB ID:	1549447

          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.
          Last edited by DasMatze; 11-08-2018, 05:33 PM.

          Comment


            #6
            Also, I kept this article in my reading list: https://80.lv/articles/removing-quat...om-3d-engines/
            They seem to explain quaternion in a new way that make them really to understand.

            Comment


              #7
              Originally posted by DasMatze View Post
              I don't think I will work on my version anytime soon.
              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!

              Comment

              Working...
              X