Random Levels in It Hungers
I thought I'd take a few minutes to quickly describe how I created random levels in It Hungers. This last minute addition to the game was really something that made it a little bit more replayable for me, even though it's a very crude addition.
The Overall Plan
The plan basically consists of a grid of positions within an arena. I would then essentially shuffle a deck of tiles, rotate them, and place them into the arena. These vignettes are each responsible for populating themselves with the prefabs that inhabit them, like enemies or pickup items.
The Grid
It's not much to look at, but the grid is basically several game objects out in the world.

Pretty uninspiring, right? That's where my VignetteManager comes to the rescue!
The Vignette Manager
The vignette manager's job is to know where all of the game positions are for these tiles. Generates a random "deck" of tiles, shuffles it, and rotates each tile as it places it down into the game. Each tile then populates itself, or in the case of "special" tiles like the player spawn or the larva spawn, it handles them accordingly. This is a little bit clunky, but the shuffling function basically randomly selects an item in a List (array) of available locations. It "draws" that tile from the stack, and places it into a "shuffled" stack. Basically, all it's doing is rearranging the order of the tiles.
``` Transform randomListVignetteTransform() { Transform selectedVignetteTransform;
int index = Random.Range((int)0,(int)shufflingVignettes.Count); //picks a random array index
selectedVignetteTransform = shufflingVignettes[index];
shufflingVignettes.RemoveAt(index); // removes that index from the unshuffled version of the list
shuffledVignettes.Add(selectedVignetteTransform); // adds it to the shuffled version
return selectedVignetteTransform; // and returns the transform of the empty placeholder game object in the list
}
```
Then, we randomly rotate in a similar way, and put a random vignette prefab in that location.
``` float randomPrefabRotation() { float randomRot; int randIndex = Random.Range((int)0, rotations.Length); randomRot = rotations[randIndex];
return randomRot;
}
GameObject randomPrefab()
{
GameObject randomGO;
int randIndex = Random.Range((int)0, vignettes.Length);
randomGO = vignettes[randIndex];
return randomGO;
}
```
You may have noticed by now, that each of these bits are really doing the same thing: grabbing random items from a list. These random things are basically random obstacles or meshes, that have not been populated yet with any denizens or items in the game.
Filling out the Vignette
The last little bit was putting something in each of these vignette tiles. Basically, I really did the same thing. A random list of "things" in an empty game object. The Start method randomly instantiates an item from that list, and the placeholder game object deletes itself.
``` public class RandomSpawnControl : MonoBehaviour { public GameObject[] enemySpawnerGO; public GameObject mapGOParent; public GameObject spawnParentGO;
// Start is called before the first frame update
void Start()
{
spawnParentGO = GameObject.FindWithTag("MapGOTagger");
GameObject goInstantiated;
GameObject objToSpawn = enemySpawnerGO[Random.Range((int)0, enemySpawnerGO.Length)];
goInstantiated = Instantiate(objToSpawn, this.transform.position, this.transform.rotation);
goInstantiated.transform.SetParent(spawnParentGO.transform);
Destroy(this.gameObject);
}
}
```
These enemySpawnerGO game objects are enemies, items, and spawners.
You can see that I've cheated a little bit, and seeded these elements to favor some things more than others. Once this has all been instantiated, you've got yourself a level!

Thinking like a Boardgame
I sort of knew what I was getting into with random levels. I've looked at it so many different ways, and ran out of time trying to do it in a previous Ludum Dare. This time, the Ah Ha moment was thinking like it was a board game. These weren't "random levels" they were tiles or cards being drawn from a deck. Pick a random place, draw a random card, place it, and remove the possibility of "drawing" that same location again. I know it's a mess and could use more work. But look at it! It was a 30 minute effort and really made it feel like there is more game there.
The full code can be found buried here: https://github.com/ArkInRev/LD46
You can check out the game here: https://ldjam.com/events/ludum-dare/46/it-hungers
If you stuck it out this far, thanks for reading and I hope it helps someone!