itch.io is community of indie game creators and players

Devlogs

Devlog #2.3: Burst-compatible biome proceducer

YNL - Vozel (Devlog)
A downloadable game

🔶 Better maintainable approach

For biome calculation, instead of the classic approach of using a giant switch-case to call the right static method for each biome, I wanted something more maintainable and efficient.

The downside of the old approach is obvious: every time I add or modify a biome, I would have to go back and update the switch-case. That’s messy and hard to scale.

To solve this, I used a [BiomeProducer(int biomeID)] attribute. Each biome has its own static class decorated with this attribute and implements a voxel-processing method with a consistent function signature. Using Reflection, I can automatically collect all these methods and bake them into a NativeHashMap.

The neat part is that Burst compiler supports FunctionPointer<T>, which means I can turn those static methods (grabbed via Reflection delegates) into actual function pointers that Burst can compile and call directly. This makes the biome producer system both powerful and extensible: adding a new biome is as simple as writing a new class with the attribute—no need to touch the core code.

For example:

[BurstCompile, BiomeProducer(BiomeType.A)]
public static class ABiomeProducer 
{
    [BurstCompile]
    public unsafe static ushort GetVoxelValue(int3* p, int seed)
    {
        return 0; 
    }
}

As you can see, the producer functions can only use primitive types or pointers as parameters, to stay compatible with Burst.

🔶 Proceducer implementation problem

While working on biome producers, I realized that constantly writing methods with the exact required signature was a bit of a hassle. Using a abstract class instead of attribute could solve part of the problem, but it introduced another issue: sometimes I would forget to add the [BurstCompile] attribute.

To fully solve this, I decided to leverage Roslyn analyzers. I created a ruleset that:

  • Reports errors if a biome producer is missing the required method.
  • Reports errors if the method has the wrong signature.
  • Reports errors if [BurstCompile] is missing.

On top of that, I implemented a fix provider using source generation to automatically add or correct the code when these errors occur.

Now, all I have to do is declare a [BiomeProducer] attribute, and with a single click, all the necessary methods and attributes are generated automatically. This ensures my code always follows the standard, while also saving a huge amount of time when extending the biome system.

Leave a comment