Procedural Room Content Generation

Hello, I’m having some trouble thinking of a good way to design randomization and procedural content in my top-down 2D game.

The way I’m handling each room is by creating a “Room Template Prefab” (by the suggestions in This thread), which is a pre-made layout of a room. It contains floor tiles, walls and colliders, 4 potential doors, and various “static” elements. I currently have two different RoomTemplate prefabs. When I generate the layout of the Level (a series of connections between rooms), I instantiate a random template from a list of prefab references and setup the door connections for that instance. Only the room the player currently occupies in enabled at any time.

My issue currently is setting up a way to generate content specific to each template and separated into different “RoomTypes” (like Boss, Shop, Treasure, etc.) without having a huge nest of GameObjects for each template prefab… if possible…

The only idea I’ve had so far was to create a “ContentLayout” script and GameObject that contained the logic and references for the content that could spawn, and creating a bunch of them for each RoomTemplate, and for each possible room type. I would then store references to these prefabs in a manager class in a way that i could grab the proper “ContentLayout” for the room I’m generating… if that made any sense… lol

Anyway, would this be a good place to start? I’m worried about the memory and performance cost of this kind of setup… is a bunch of prefab references something that should be avoided? Any ideas would be very appreciated!

I think prefabs referencing other prefabs is the way to go. You could create “Room Content Template” prefabs. Then you don’t need a manager class. Something like:

public class RoomTemplate : MonoBehaviour {

    public RoomContentTemplate[] contentTemplateLibrary;
   
    public void InstantiateRoom() {
        // Randomly choose a content template. You could do this differently if,
        // say, you're at the last room and need it to be a Boss room.
        var i = Random.Range(0, contentTemplateLibrary.Length);
        contentTemplateLibrary[i].InstantiateContent(this.gameObject);
    }
}

public class RoomContentTemplate : MonoBehaviour {

    public GameObject[] contentLibrary;
    public int numItemsInRoom = 5;

    public void InstantiateContent(GameObject roomGameObject) {
        for (int i = 0; i < numItemsInRoom; i++) {
            var j = Random.Range(0, contentLibrary.Length);
            var item = Instantiate(contentLibrary[j]);
            item.transform.position = roomGameObject.position + contentLibrary[j].transform.localPosition;
        }
    }
}

Then you could create these prefabs:

  • (RoomContentTemplate) Treasure: [chest, weapon rack, pile of gold, trap]
  • (RoomContentTemplate) Shop: [shopkeeper, sign, anvil, shelf]
  • (RoomTemplate) 4_Door_Dungeon: [Shop, Treasure]
  • (RoomTemplate) 1_Door_Cavern: [Treasure, Boss]
1 Like