Procedural Dungeon Generation

From PSwiki
Jump to navigation Jump to search

PlaneShift random dungeon generator

Core System:

  • pre-made rooms with explicit connection points.
  • Ensure the door/entrance is exactly the same size for all the rooms.
  • In Editor you can create a room deriving it from ADungeonRoom
  • Room can be made of any number of meshes, better to keep all under a common mesh called Floor.
  • Lights all already placed in the pre-made room
  • In the Editor you should add:
    • Connection points are of class UDungeonConnection, display as box collision, the X axis should point away from the entrance.
    • Add Loot using UDungeonSpawnComponent and set the custom attribute "Spawn Type" == LOOT
    • Add traps using UDungeonSpawnComponent and set the custom attribute "Spawn Type" == TRAP, plus you can specify a trap size (which should be the size of the room walls), and trap type
    • Add a simple Box Collision object, which is covering the whole room, will be used to activate and deactivate traps when the player enters the room. You HAVE to TAG this actor with "trapsActivation"
    • Add NPCs using UDungeonSpawnComponent and set the custom attribute "Spawn Type" == NPC

Configuration

Configuration is done on the Dungeon Start object BP.

Randomization

  • For each connection we spawn another room and connect it
  • For each trap, we spawn a ADungeonTrap object, and we adjust the size based on the trap size attribute
  • We can if the new room overlaps with the other rooms, filtering on class (being the room class) to see if you can spawn it or not
  • build offline, save the rooms coordinates, then recreate online
  • at the end of the generation, for each connection left open we add a wall to close it. Can also be a special mesh for closing connections.
  • We identify all the end rooms, and start from there to place loot/traps/npcs walking backward


Placeholders:

  • furniture that can be searched (shelves, tables, ...)
  • chests
  • traps (GetRandomPointInNavigableRadius ? )
  • secret passages


Algorithm:

  • place the starting room (with at least 2 connections)
  • add all connection points to a list, and randomize, get one
  • randomize the next room and the connection you will use
  • attach it to the previous room's connection
  • check for overlaps, if it overlaps try another room, max number of tries, then change connection

What happens at runtime

1) We have a sub-level called "DungeonGeneration". In this level there is an objects called "DungeonOwner1". When the level loads we store a reference to the "DungeonOwner1" in a variable for later use.

2) A GM creates the dungeon with /dungeon or with the /dungeon window command. In the window case we go through APlaneshiftPlayerControllerBase::RequestCreateDungeon(), which then calls the /dungeon command.

3) This will call AdminManager::DungeonGeneration() , it retrieves the "DungeonOwner1" and use it for location and ownership when spawning a new "DungGenStart_BP".

4) "DungGenStart_BP" is a blueprint which holds all the possible configurations to use in the generation. This object is instantiated

Open Points NavMesh:

  • Navmesh generation is possible only if the whole world has dynamic navmesh generation. UE doesn't allow at the moment to have a mix of static and dynamic navmeshes.
  • For dynamic generation we could spawn at runtime one navmesh covering the total area where we generated the rooms.


Unreal Engine PCG - Tested = No thank you

  • You need to position your initial volume with snap to grid 100, otherwise if you are in non step position you will get a different number of points generated.
  • We need to use Transform Points to move the offset of our generated points back to the 0,0,0 position of our volume. In our example we had to use 50,50,50 as both min and max offset.
  • In the chart we use:
    • Get Actor Data -> Volume Sampler -> Transform Points -> Static Mesh Spawner
    • Volume Sampler has 100,100,100 for Voxel size
  • If you want to do it in an actor, you need a Collision Box inside the actor , so the engine can determine the overall actor size.