Procedural Levels & Logic - Inspired by Blue Prince
Inspired by the strategy puzzle adventure game Blue Prince, released on Steam Apr 10, 2025.
For a little bit of context, in Blue Prince, the player is confined mostly to a large estate, where the space within its mansion is limited to a 5x9 grid. For each grid space, the player is given 3 rooms to choose from and the chosen room is spawned, either allowing the player to move farther into the mansion or dead end. The primary goal of Blue Prince is to reach the fabled 46th room said to be deep within the mansion, but it’s connected to a locked antechamber which must be opened by solving puzzles. If you fail to do so within a certain number of “steps”, you lose and must try again.
I was intrigued by this gameplay loop in Blue Prince and decided to recreate several of its mechanics with my own vision. I went with a different approach with how progress is made. Rooms are randomly chosen, but the player must still use strategy to determine the best path forward.
Like Blue Prince, there are locked doors that require keys to open. And since doors have a random chance to be locked, the player is given 1 key at the start of the game and there are rooms which provide more. The objective is still to reach the antechamber and unlock it, allowing passage to room 46. This can be accomplished by having a cellar room be spawned, activate its switch, and reach the designated antechamber door. You win by reaching the 46th room and lose if you dead end.
The antechamber doors are their own unique blueprint and do not spawn rooms. They simply have a boolean variable to determine if they’re locked or unlocked and this variable is set to true when its assigned lever has been activated. When a player overlaps with the door and the door is unlocked, it opens.
The antechamber levers (BP_AntechamberLever) calls from a level manager blueprint placed in the scene. This level manager helps keeps track of which antechamber doors have been unlocked. When a cellar room is spawned, the lever inside references the level manager’s antechambers array, a random value is grabbed (East, West, or South), and that antechamber door is removed from the array.
With the affected antechamber set as its own variable inside the lever, on overlap with the player, the lever’s animation plays and the antechamber door is found and unlocked.
Since Blue Prince hasn’t discussed how they handled room spawning (at least to my knowledge), it took me some brainstorming to come up with a way to handle it. I eventually settled with line traces. The rooms themselves only need to be spawned when the player interacts with a door, but what can happen after is determined through actor tags.
Room doors (for spawning levels), antechamber doors, the world boundaries, and room walls each have their own actor tag designated. When a room is spawned, a line trace is drawn from the origin of the room to the door. If that line trace hits any actor between its start/end location with one of these designated tags, the appropriate events carry out.
Does it hit a wall? Set itself to be closed (spawning levels no longer allowed) and make the blockade mesh visible.
Does it hit another door that’s closed? Open that door and destroy self.
Does it hit another door that’s already opened? Destroy self.
Does it hit an antechamber door? Then grab the level manager and make it be known that it’s reachable. (Used for game over events.)
Does a wall hit a door? Room walls also have their own trace. If successful, close the door and set it to be a blockade.
Below are some videos showcasing this logic, except the antechamber which has already been shown:
As for the room designs themselves, I made a base room level template which all of rooms are created from. This ensures there are no gaps or seams when they are spawned in and connected to each other. Each room has a floor size of 1400uu² (Unreal Units) and each door blueprint has a cube mesh 700uu away to be used as the level instance’s spawn transform. The red arrow points towards the door which connects to the previous room.
Rooms that have walls need a blocking volume (with the “Wall” tag) to be added along that side.