Binding of Isaac like procedural level generation

Hello everybody,

I am currently trying to make a room based procedural level generation system and I am quite stuck at the moment. I’ve made two different iterations of something I thought would work but both systems weren’t flexible enough or had weird issues.

The game is in 3D but all on the same plane, so effectively this only needs to be a 2D level generator.

This is what I had in mind:

(I apologise for my lack of artistic talent)

The idea is to have multiple room prefabs (some with different sizes) based on a standardised room size and then have the procedural room generator place them all in random orientations.
I’d also like to have the option to decide where the doorways are allowed to be placed (so I can have a room where one wall is covered in some sort of decoration for example) but this isn’t necessary.
There should obviously not be any isolated rooms with no doors either.
Lastly I’d like the system to be based off of a seed, so I can regenerate the same level multiple times.

At this point I have made two different systems, both with major flaws I couldn’t figure out how to solve.

In my first system I was placing the rooms as actors on an auxiliary actor (the doorway marker). This caused an issue with odd shaped rooms and obviously made a sort of diamond shape, as it was moving outwards from a single spot. furthermore I thought it wasn’t very good that the room actor’s root was sort of offset (so on the point where the entrance would be)

My second system had similar flaws, except for the fact that it is a lot more complex and has unexplainable, seemingly random overlapping rooms.

I have already seen these two threads, but couldn’t get something out of them that worked for me:
https://forums.unrealengine.com/development-discussion/blueprint-visual-scripting/21353-zelda-esque-dungeon-creation-binding-of-isaac-style
https://forums.unrealengine.com/development-discussion/blueprint-visual-scripting/21191-random-map-generation-looking-for-suggestions-on-a-different-implementation

Thank you for any help!

1 Like

I’ve had various run ins with randomly generated levels.

The conclusion I came to is that it’s MUCH easier to generate stuff on the fly, rather that get it all ready beforehand.

I don’t know if that’s applicable to you.

Two main problems with doing it all beforehand are

  1. The map uses a lot of resources even though the player is only ever in one room

  2. You have to deal with overlapping rooms, this is nowhere near as bad if you make it on the fly.

As far as the ‘attaching’ actors go, this is the approach I ended up with. And it works fine if you do it right. Each ‘module’ needs to be a BP and the attach point is actually a scence or an arrow as a component with that BP. The way, you can see where things are going to fit and you get the transform to spawn the new object all in one go.

If any of this is remotely relevant please come back to me.

The issue I have with doing it on the fly is that I want the level to be persistent.
The plan is to have a game set in a procedural world that persists for a longer while across the save. It isn’t meant to be a new level every time you boot the game, but rather a new level for every new save or character. That’s why I need to have it seed based. I don’t want any overlaps simply because the game is set underground on the same height and overlaps wouldn’t work on a map view

I already had that working, it’s just that the system wasn’t fully able to tell if the room would fit.

Ok, see what you mean. Got your work cut out there :slight_smile:

My first though is that I would make rooms with unit sizes, so that they fit perfectly into a grid. For example:


Note that every door is exactly 1 unit long. Every room has a 2D array of the size of it’s bounds. For the example this would be an 8x8 array. Every element of the array states if the grid is occupied at this place.

Now I can make a 2D array in the same way for the whole level. If I want to place a room in it, I’ll make a check if any of the occupied elements are overlapping. Then I cannot place it there.

I can now place an initial room in the “level-grid” and for every door in this room I check which other rooms would fit. For the rooms fitting, I would choose a random one with a seed (see Random Streams | Unreal Engine Documentation).

This should work, it’s just a bit brainf*** with 2D arrays.