Procedural Generation

Procedural Generation

Note

This is an advanced topic, so it is preferred that you already have some experience modding Astroneer.

Procedural generation in astroneer is done using their custom generation graph that for shipping games gets compiled to low-level code.

Thus we cannot easily change a lot of its behaviors, but what we can do, is use already existing behaviors and modify them a little bit.

To generate our object we must have a Procedural Placement and a Procedural Modifier class in our mod files.

Procedural Modifier is like a model of spawning, the only settings we can change are Procedural Placement which is perfect because that is what we will be doing. Procedural Placement is placements that are actually responsible for spawning your items.

Before creating them though, we must know that there is a restriction on filenames that dictate procedural generation in your mod.

This restriction comes from the Astroneer has a lot of its generation code compiled to low-level asm.

In your modkit you can find the file that describes procedural generation names restrictions in Content/Mods/localcc/TPuzzle/proceduralGenerationModels.json.

This is a json file that contains an object. Keys in this object are valid names for Procedural Modifier classes.

Keys can also be treated as “Models” that we can choose from to get different spawning behaviors.

Values for each key are valid names for Procedural Placement classes that the Procedural Modifier can contain.

Note

Models work cross-biome but not cross-planet (e.g. you can use Forests_Terran_Props for the Plains biome on Terran planet, but you cannot use it for Arid planet)

Planets in this tutorial are called not by their name, but by their type, because that is how the game stores them.

To create those files, right click in the content browser go to Miscellaneous and select Procedural Modifier.

We will name this one Plains_Terran_Puzzles.

Then right click in the content browser again, and this time select Procedural Placement.

We will name this one ObjPl_Puzzle_Surface_Terran.

Open this asset and set the following parameters:

  • Seed: Set this to whatever.

  • Radius: 600. Radius determines how far objects will be spawned from eachother, treat is if it was objects rarity.

  • Max Projection Distance: 1500 This is probably max distance the objects can be from eachother.

Warning

Radius should always be <= Max Projection Distance, otherwise no objects will be spawned.

Now the fun part, spawning the objects. Open variants and click +.

In this variant set the following parameters:

  • Selection Weight: 1.0. This probably determines the chance for this variant to spawn in case there is more than one variant.

  • Placement Actor: The actor you want to spawn.

  • Item Type: This is for resources, if you want custom resource nodes you should set this to the resource type you want to spawn, and Placement Actor to Decorator_MineralFlecks.

  • Orientation: Align to planet up. This determines how your object will be aligned when spawned.

  • Random Yaw: Max object random yaw when spawning.

  • Random Pitch: Max object random pitch when spawning.

  • Uniform scale: Check this.

  • Scale XYZ: Set min to 1.0 and max to 1.0. This will choose a random scale between min and max when spawning your object.

  • Density scaling slop: Set min to 1.0 and max to 1.0.

  • Cull distance: Set min to 23000` and max to ``25000. This determines how far away the spawned object can be from the camera before it is culled.

  • Enable Density Scaling: Uncheck this.

  • Cast Shadow: Check this. This determines whether the spawned object will cast shadow.

  • Cast Shadow as Two Sided: Uncheck this. This determines whether the spawned object will cast shadow as if it had a two-sided shader.

  • Receives decals: Uncheck this.

  • Use as occluder: Uncheck this. This probably should be checked for very large objects.

  • Should override destruction effects: Uncheck this.

After setting up the Procedural Placement we need to add it to the Procedural Modifier.

Open your Procedural Modifier asset and add a compiled placement. Set the compiled placement to the one we just created.

Cook the mod files and copy them over to the mod directory.

Writing the metadata

Procedural generation requires a metadata entry to work.

This is an example of what your file should look like

{
    "schema_version": 2,
    "name": "ExampleMod",
    "mod_id": "ExampleMod",
    "author": "YOUR_NAME",
    "description": "An Example Mod",
    "version": "0.1.0",
    "sync": "serverclient",
    "integrator": {
        "item_list_entries": {
            "/Game/Items/ItemTypes/MasterItemList": {
                "ItemTypes": [
                    "/Game/Mods/YOUR_NAME/TutorialMod/ExampleItem_IT"
                ]
            }
        },
        "biome_placement_modifiers": [
            {
                "planet_type": "Terran",
                "biome_type": "Surface",
                "biome_name": "Plains",
                "layer_name": "None",
                "placements": [
                    "/Game/Mods/YOUR_NAME/TutorialMod/Plains_Terran_Puzzles"
                ]
            }
        ]
    }
}

This will add the procedural modifier to the plains biome on a terran planet.

To get which biomes/layers you can use on which planets there is a file at Content/Mods/localcc/TPuzzle/biomeData.json.

For example we want to add something to the valleys biome on exotic planet. In the file we will see something like this:

{
    "Exotic": {
        "SurfaceBiomes": {
            "Hills_Exotic": {
                "Layers": [
                "None"
                ]
            },
            "Valleys_Exotic": {
                "Layers": [
                "None"
                ]
            },
            "Rolling_Exotic": {
                "Layers": [
                "None"
                ]
            },
            "Mountains_Exotic": {
                "Layers": [
                "None"
                ]
            }
            },
            "CrustBiome": {
            "Layers": [
                "CrustExotic1",
                "CrustExotic2",
                "CrustExotic3",
                "CrustExotic4"
            ]
        }
    }
}

To add a procedural modifier to a biome we must know planet_type, biome_type, biome_name and layer_name.

In this file we find an object with key Exotic, the key corresponds to planet_type.

In this object we see two biome types, SurfaceBiomes and CrustBiome. We know that valleys are a surface biome, so we look inside the SurfaceBiomes object.

Also note that this means that biome_type is Surface.

Here we can see all of the avaiilable surface biomes, we want valleys so look at Valleys_Exotic, this becomes our biome_name.

This biome contains only one layer, but we still must specify it, in this case it’s None.

But now that we chose the biome, we must know that file names that we chose previously do not match the one permitted for exotic planet, this must be fixed.

Rename Plains_Terran_Puzzles to Valleys_Exotic_Puzzles.

Also rename ObjPl_Puzzle_Surface_Terran to ObjPl_Puzzle_Surface_Exotic.

Our metadata.json file should look something like this:

{
    "schema_version": 2,
    "name": "ExampleMod",
    "mod_id": "ExampleMod",
    "author": "YOUR_NAME",
    "description": "An Example Mod",
    "version": "0.1.0",
    "sync": "serverclient",
    "integrator": {
        "item_list_entries": {
            "/Game/Items/ItemTypes/MasterItemList": {
                "ItemTypes": [
                    "/Game/Mods/YOUR_NAME/TutorialMod/ExampleItem_IT"
                ]
            }
        },
        "biome_placement_modifiers": [
            {
                "planet_type": "Exotic",
                "biome_type": "Surface",
                "biome_name": "Valleys_Exotic",
                "layer_name": "None",
                "placements": [
                    "/Game/Mods/YOUR_NAME/TutorialMod/Valleys_Exotic_Puzzles"
                ]
            }
        ]
    }
}

Now cook the mod and verify you see objects spawning.