Skip to main content

Custom generator

It is possible to implement a custom layout generator if you want to generate levels that are not officially supported. The benefit of that is that you can still leverage the whole Frigga framework and automatically apply a Theme after the layout is generated.

Rectangle generator is an example of a custom generator. Instead of generating complex levels like the Walker generator, it produces simple rectangular levels or rooms.

warning

The custom generator API is experimental. There might be some breaking changes in the future while the API matures.

Setup

For now, the setup is present as commented code:

using System.Collections.Generic;
using Frigga;
using UnityEngine;

// Each generator must inherit from the GeneratorBase class
public class SquareGenerator : GeneratorBase
{
// Each generator usually needs at least 2 int grid tiles to work with
// The IntGridTilePicker property drawer will show a dropdown with available tiles from the assigned Theme
[IntGridTilePicker] public int FloorTile = -1;
[IntGridTilePicker] public int WallTile = -1;

// We can put more fields here and then should automatically appear in the inspector
public int BorderSize = 5;

// The GenerateLayout contains the main logic of the generator
protected override IEnumerable<GeneratorProgress> GenerateLayout(GeneratorResult result)
{
// Use the Random variable as the source of randomness
var size = Random.Next(10, 20);

// We need to create an Int grid object where we store the mapping from grid positions to tiles
var intGrid = new IntGrid();

// Place the tiles
for (var i = -BorderSize; i < size + BorderSize; i++)
{
for (var j = -BorderSize; j < size + BorderSize; j++)
{
// Based on the indices, we decide if Wall or Floor tile should be used
if (i < 0 || i > size - 1 || j < 0 || j > size - 1)
{
// We need to place the tile inside the Int grid using the SetTile method
intGrid.SetTile(new Vector3Int(i, j), WallTile);
}
else
{
intGrid.SetTile(new Vector3Int(i, j), FloorTile);
}

// We can animate the generator process by returning the int grid object after each iteration
if (result.IsAnimated)
{
yield return new GeneratorProgress()
{
IntGrid = intGrid
};
}
}
}

// Do not forget to assign the int grid object in the result object
result.IntGrid = intGrid;

// If we decide not to animate the generator, we might need to "yield break;" at the end of the method
// yield break;
}

// Inside the ValidateConfiguration we can check the configuration of the generator
// If there is something wrong with the configuration, we return a list of errors
protected override List<string> ValidateConfiguration()
{
var errors = new List<string>();

// For example, we can check whether the Border size is at least 0
if (BorderSize < 0)
{
errors.Add("Border size must not be less than 0");
}

return errors;
}
}