Intro
Demonstration of Procedural Content Generation in Unity to create terrain with distinct biomes (e.g., hills + mountains) using Perlin noise, hierarchical nodes, and mapping functions for controlled feature placement.
Setup
- Create a Terrain object in Unity.
- Add a C# script (e.g.,
BiomeTerrainGenerator). - Include
using UnityEngine;. - Start with a flat base terrain to allow additive/subtractive shaping.
- Use seeded randomness for reproducibility.
Saving and Loading Configurations
- Create a ScriptableObject to store terrain configuration (noise settings, max/base values, node hierarchy).
PCGTerrainData.asset%YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!114 &11400000 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 0} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: df2799923c76d2842b535aa8cabb0d08, type: 3} m_Name: PCGTerrainData m_EditorClassIdentifier: Config: - Name: Terrain XOffset1000: 0 XOffset100: 0 XOffset10: 0 XOffset1: 0 YOffset1000: 0 YOffset100: 0 YOffset10: 0 YOffset1: 0 ZOffset: 0 MaxValue: 0 PerlinScalar: 0 UseAbsVal: 0 GenNoiseType: 0 ProcessParentType: 0 CombineType: 0 ProcessParentVariables: [] Complement: 0 Mute: 0 DoNotProcessDescendants: 0 PCGConfigChildren: [] GenNoiseCurve: serializedVersion: 2 m_Curve: - serializedVersion: 3 time: 0 value: 0 inSlope: 1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 - serializedVersion: 3 time: 1 value: 1 inSlope: 1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 ProcessParentCurve: serializedVersion: 2 m_Curve: - serializedVersion: 3 time: 0 value: 0 inSlope: 1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 - serializedVersion: 3 time: 1 value: 1 inSlope: 1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 guid: m_storage: 002cef59-a56c-421f-bac0-3aa10876c3f0
-
To save a configuration, click the save button
-
To load a configuration:
- Drag the ScriptableObject into the config field in your terrain generator script.
- Click a Load button (or call a
LoadConfig()function) to synchronize all nodes with the selected configuration.
-
Always load after switching configs to ensure all nodes reference the current ScriptableObject.
-
Use duplicate or versioning (
Ctrl+D/Cmd+D) to experiment with multiple terrain setups.
Trapezoid & Mapping Curves
Trapezoid functions are used to control where features appear on your terrain. In PCG, they often serve as fall-off maps or distance-based masks, defining boundaries for landmasses like islands, plateaus, or biome regions.
Mathematical Logic
-
A 1D trapezoid is defined by four points: (start rise), (start plateau), (end plateau), (end fall).
-
Terrain logic:
- Peak Area: Heights remain at 100% of the noise value.
- Sloped Area: Heights interpolate linearly from the peak to the base.
- Base Area: Heights are clamped to 0 (water level).
-
Often simplified to a radial or square gradient for 2D terrain.
Trapezoid Example Table
| Element | x | y | | ------- | --- | - | | 0 | 0.5 | 0 | | 1 | 0.6 | 1 | | 2 | 1 | 1 | | 3 | 1 | 0 |
PCG Nodes Overview
Abstract
Terrain βββ Biomes βββ MountainBiome β βββ MountainBase β βββ MountainDetail β βββ HillsBiome βββ HillsBase βββ HillDetail βββ Stones
Terrain (Root) Node
- Turn off Perlin Scalar and set Max Value to ~0.2 to provide room for carving away (subtracting) from terrain
Terrain Node
- Max Value: 0.212
- Perlin Scalar: 0
- Gen Noise Type: 2
- Process Parent Type: 0
- Combine Type: 0
Biomes
- The Biomes node will tell us the probability weβre in a particular node
- Perlin Scalar = 4.1
- Max Value: 0.825
Biomes Node
- Max Value: 0.79
- Perlin Scalar: 4.1
- Gen Noise Type: 0
- Process Parent Type: 0
- Combine Type: 0
Biome: Mountains
Goal: Large peaks with height variation and detail.
- Child nodes
MountainBaseβ low-frequency noise for broad mountain shapes.MountainDetailβ high-frequency noise for peaks and subtle features.
Create MountainBiome node
- Add a Mountain biome node under the root probability map.
- Assign low-frequency Perlin noise for base shape.
- Use trap or mapping curves to select mountain regions.
- Example: values 0.5β0.6 β plateau β mountains appear only in this range.
- Define trapezoid (shown at Max Value = 1), then set to 0
MountainBiome Node
- Max Value: 0
- Perlin Scalar: 0
- Gen Noise Type: None
- Process Parent Type: Trapezoid [0.45, 0.6, 1, 1]
- Combine Type: Multiply
MountainBase
MountainBase Node
- Max Value: 0.361
- Perlin Scalar: 7.4
- Gen Noise Type: 0
- Process Parent Type: 0
- Combine Type: 0
MountainDetail
MountainDetail Node
- Max Value: 0.24
- Perlin Scalar: 28.4
- Gen Noise Type: 0
- Process Parent Type: 0
- Combine Type: 0
Refine Features
- Smooth curves to remove artifacts from trapezoid function.
- Adjust max/base values to control intensity.
-
Lower trapezoid slope
-
lower mountain base (max = 0.361)
Tips:
- Only mountain child nodes should affect mountain areas.
- Use mapping curves for smoother transitions.
Biome: Hills
Goal: Rolling terrain with smaller hills and scattered features.
- Use trap or mapping curves to define hill regions.
HillBaseβ basic hill shapes.HillDetailβ curl/noise for surface texture.Stonesβ isolate high noise values for small rocks.
Create HillsBiome Node
- Add a Hills biome node under the root probability map.
- Assign mid-frequency Perlin noise for hills.
- raised to 1 to show shape
HillsBiome Node
- Max Value: 0.241
- Perlin Scalar: 0
- Gen Noise Type: None
- Process Parent Type: Trapezoid [0, 0, 0.25, 0.5]
- Combine Type: Multiply
HillsBase
HillsBase Node
- Max Value: 0.263
- Perlin Scalar: 8.4
- Gen Noise Type: 0
- Process Parent Type: 0
- Combine Type: Add
Refine Features
- Blend transitions between hills and mountains using mapping curves.
- Avoid doubling contributions by carefully managing child hierarchy.
- Adjust HillsBiome to make hills smoother
- Trapezoid: [0, 0, 0.25, 0.5]
- The hill is fully engaged from 0 to 0.25 and then ramps down to 0.5
- Trapezoid: [0, 0, 0.25, 0.5]
- Adjust hillsBase down a bit, max = 0.263
HillDetail
HillDetail Node
- Max Value: 0.023
- Perlin Scalar: 28.9
- Gen Noise Type: 0
- Process Parent Type: 0
- Combine Type: 0
Stones
Stones Node
- Max Value: 0.223
- Perlin Scalar: 18.2
- Gen Noise Type: Perlin Noise with mapping curve
- Process Parent Type: *Zero Out
- Combine Type: 0
- Use Perlin Noise with Mapping Curve to isolate the highest values (stal)
- Create sunken/erosion areas around the stones
- Can switch to subtract to create pockmark areas
Tips:
- Curves control placement frequency and intensity of stones or small features.
Adjust
- In HillsBiome, the linear interpolation from the trapezoid function caused an artifact
- Switch to Mapping Curve β Process Parent Curve to use smoother, non-linear curves
Visualization & Testing
- Visualize probability maps for biome coverage.
- Adjust terrain max/base values to see feature placement.
- Test different config versions and tweak curves for smoother transitions.
- Keep code modular: separate noise generation, mapping, and object placement.
Final Config
Abstract
Terrain (Perlin: 0, Max: 0.212) βββ Biomes (Perlin: 4.1, Max: 0.79) βββ MountainBiome (Perlin: 0, Max: 0, Mask: Trapezoid [0.45, 0.6, 1, 1], Combine: Multiply) β βββ MountainBase (Perlin: 7.4, Max: 0.361) β β βββ MountainDetail (Perlin: 28.4, Max: 0.24) β βββ HillsBiome (Perlin: 0, Max: 0, Mask: Mapping Curve [[0, 0, 0.25, 0.5], Combine: Multiply) βββ HillsBase (Perlin: 8.4, Max: 0.263) β βββ HillDetail (Perlin: 28.9, Max: 0.023) β βββ Stones (Perlin: 18.2, Max: 0.223, Perlin Noise with mapping curve, zero out)
0.0 βββββββ hills
0.3 βββββββ hills
0.5 βββββββ mountains
0.7 βββββββ mountains
1.0 βββββββ maybe nothing (depends)
PCGTerrainData.asset%YAML 1.1 %TAG !u! tag:unity3d.com,2011: --- !u!114 &11400000 MonoBehaviour: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 0} m_Enabled: 1 m_EditorHideFlags: 0 m_Script: {fileID: 11500000, guid: df2799923c76d2842b535aa8cabb0d08, type: 3} m_Name: PCGTerrainData m_EditorClassIdentifier: Config: - Name: Terrain XOffset1000: 0 XOffset100: 0 XOffset10: 0 XOffset1: 0 YOffset1000: 0 YOffset100: 0 YOffset10: 0 YOffset1: 0 ZOffset: 0 MaxValue: 0.212 PerlinScalar: 0 UseAbsVal: 0 GenNoiseType: 2 ProcessParentType: 0 CombineType: 0 ProcessParentVariables: [] Complement: 0 Mute: 0 DoNotProcessDescendants: 0 PCGConfigChildren: - m_storage: a57442cf-1fd2-4dff-ba95-7c5652167a0e GenNoiseCurve: serializedVersion: 2 m_Curve: - serializedVersion: 3 time: 0 value: 0 inSlope: 1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 - serializedVersion: 3 time: 1 value: 1 inSlope: 1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 ProcessParentCurve: serializedVersion: 2 m_Curve: - serializedVersion: 3 time: 0 value: 0 inSlope: 1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 - serializedVersion: 3 time: 1 value: 1 inSlope: 1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 guid: m_storage: 002cef59-a56c-421f-bac0-3aa10876c3f0 - Name: Biomes XOffset1000: 0 XOffset100: 0 XOffset10: 0 XOffset1: 0 YOffset1000: 0 YOffset100: 0 YOffset10: 0 YOffset1: 0 ZOffset: 0 MaxValue: 0.79 PerlinScalar: 4.1 UseAbsVal: 0 GenNoiseType: 0 ProcessParentType: 0 CombineType: 0 ProcessParentVariables: [] Complement: 0 Mute: 0 DoNotProcessDescendants: 0 PCGConfigChildren: - m_storage: 7f4758bd-e376-42eb-bb8e-be1380c4d558 - m_storage: a150cbf5-9f37-4f0f-af1d-7db0b6908c00 GenNoiseCurve: serializedVersion: 2 m_Curve: - serializedVersion: 3 time: 0 value: 0 inSlope: -1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 - serializedVersion: 3 time: 1 value: 1 inSlope: 1 outSlope: -1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 ProcessParentCurve: serializedVersion: 2 m_Curve: - serializedVersion: 3 time: 0 value: 0 inSlope: -1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 - serializedVersion: 3 time: 1 value: 1 inSlope: 1 outSlope: -1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 guid: m_storage: a57442cf-1fd2-4dff-ba95-7c5652167a0e - Name: MountainBiome XOffset1000: 0 XOffset100: 0 XOffset10: 0 XOffset1: 0 YOffset1000: 0 YOffset100: 0 YOffset10: 0 YOffset1: 0 ZOffset: 0 MaxValue: 0 PerlinScalar: 0 UseAbsVal: 0 GenNoiseType: 2 ProcessParentType: 1 CombineType: 3 ProcessParentVariables: - 0.45 - 0.6 - 1 - 1 Complement: 0 Mute: 0 DoNotProcessDescendants: 0 PCGConfigChildren: - m_storage: 19e4df50-8061-41e5-aa5a-13b87214ab16 GenNoiseCurve: serializedVersion: 2 m_Curve: - serializedVersion: 3 time: 0 value: 0 inSlope: -1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 - serializedVersion: 3 time: 1 value: 1 inSlope: 1 outSlope: -1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 ProcessParentCurve: serializedVersion: 2 m_Curve: - serializedVersion: 3 time: 0 value: 0 inSlope: -1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 - serializedVersion: 3 time: 1 value: 1 inSlope: 1 outSlope: -1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 guid: m_storage: 7f4758bd-e376-42eb-bb8e-be1380c4d558 - Name: MountainBase XOffset1000: 0 XOffset100: 0 XOffset10: 0 XOffset1: 0 YOffset1000: 0 YOffset100: 0 YOffset10: 0 YOffset1: 0 ZOffset: 0 MaxValue: 0.361 PerlinScalar: 7.4 UseAbsVal: 0 GenNoiseType: 0 ProcessParentType: 0 CombineType: 0 ProcessParentVariables: [] Complement: 0 Mute: 0 DoNotProcessDescendants: 0 PCGConfigChildren: - m_storage: ecdd57a3-f5c2-4e00-b552-b69973a88261 GenNoiseCurve: serializedVersion: 2 m_Curve: - serializedVersion: 3 time: 0 value: 0 inSlope: -1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 - serializedVersion: 3 time: 1 value: 1 inSlope: 1 outSlope: -1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 ProcessParentCurve: serializedVersion: 2 m_Curve: - serializedVersion: 3 time: 0 value: 0 inSlope: -1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 - serializedVersion: 3 time: 1 value: 1 inSlope: 1 outSlope: -1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 guid: m_storage: 19e4df50-8061-41e5-aa5a-13b87214ab16 - Name: MountainDetail XOffset1000: 0 XOffset100: 0 XOffset10: 0 XOffset1: 0 YOffset1000: 0 YOffset100: 0 YOffset10: 0 YOffset1: 0 ZOffset: 0 MaxValue: 0.24 PerlinScalar: 28.4 UseAbsVal: 0 GenNoiseType: 0 ProcessParentType: 0 CombineType: 0 ProcessParentVariables: [] Complement: 0 Mute: 0 DoNotProcessDescendants: 0 PCGConfigChildren: [] GenNoiseCurve: serializedVersion: 2 m_Curve: - serializedVersion: 3 time: 0 value: 0 inSlope: -1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 - serializedVersion: 3 time: 1 value: 1 inSlope: 1 outSlope: -1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 ProcessParentCurve: serializedVersion: 2 m_Curve: - serializedVersion: 3 time: 0 value: 0 inSlope: -1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 - serializedVersion: 3 time: 1 value: 1 inSlope: 1 outSlope: -1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 guid: m_storage: ecdd57a3-f5c2-4e00-b552-b69973a88261 - Name: HillsBiome XOffset1000: 0 XOffset100: 0 XOffset10: 0 XOffset1: 0 YOffset1000: 0 YOffset100: 0 YOffset10: 0 YOffset1: 0 ZOffset: 0 MaxValue: 0 PerlinScalar: 8.4 UseAbsVal: 0 GenNoiseType: 2 ProcessParentType: 2 CombineType: 3 ProcessParentVariables: - 0 - 0 - 0.25 - 0.5 Complement: 0 Mute: 0 DoNotProcessDescendants: 0 PCGConfigChildren: - m_storage: 26f90732-eec3-4ac1-9452-3eeff552738f GenNoiseCurve: serializedVersion: 2 m_Curve: - serializedVersion: 3 time: 0 value: 0 inSlope: -1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 - serializedVersion: 3 time: 1 value: 1 inSlope: 1 outSlope: -1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 ProcessParentCurve: serializedVersion: 2 m_Curve: - serializedVersion: 3 time: 0.00024365234 value: 0.9991787 inSlope: 0 outSlope: 0 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 - serializedVersion: 3 time: 0.253566 value: 0.9952796 inSlope: -0.11121826 outSlope: -1.2733887 tangentMode: 0 weightedMode: 0 inWeight: 0.36880788 outWeight: 0.1546173 - serializedVersion: 3 time: 0.48064685 value: 0.0297077 inSlope: -0.068615496 outSlope: -0.52867174 tangentMode: 0 weightedMode: 0 inWeight: 0.5090208 outWeight: 0.29572657 - serializedVersion: 3 time: 1.0004883 value: -0.010360718 inSlope: 0 outSlope: 0 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 guid: m_storage: a150cbf5-9f37-4f0f-af1d-7db0b6908c00 - Name: HillsBase XOffset1000: 0 XOffset100: 0 XOffset10: 0 XOffset1: 0 YOffset1000: 0 YOffset100: 0 YOffset10: 0 YOffset1: 0 ZOffset: 0 MaxValue: 0.263 PerlinScalar: 8.4 UseAbsVal: 0 GenNoiseType: 0 ProcessParentType: 0 CombineType: 0 ProcessParentVariables: [] Complement: 0 Mute: 0 DoNotProcessDescendants: 0 PCGConfigChildren: - m_storage: d8af6b06-bfff-47fd-869a-fcb4a09abc56 - m_storage: 26de7ffd-1067-4532-9174-b040c231f8df GenNoiseCurve: serializedVersion: 2 m_Curve: - serializedVersion: 3 time: 0 value: 0 inSlope: -1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 - serializedVersion: 3 time: 1 value: 1 inSlope: 1 outSlope: -1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 ProcessParentCurve: serializedVersion: 2 m_Curve: - serializedVersion: 3 time: 0 value: 0 inSlope: -1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 - serializedVersion: 3 time: 1 value: 1 inSlope: 1 outSlope: -1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 guid: m_storage: 26f90732-eec3-4ac1-9452-3eeff552738f - Name: HillDetail XOffset1000: 0 XOffset100: 0 XOffset10: 0 XOffset1: 0 YOffset1000: 0 YOffset100: 0 YOffset10: 0 YOffset1: 0 ZOffset: 0 MaxValue: 0.023 PerlinScalar: 28.9 UseAbsVal: 0 GenNoiseType: 0 ProcessParentType: 0 CombineType: 0 ProcessParentVariables: [] Complement: 0 Mute: 0 DoNotProcessDescendants: 0 PCGConfigChildren: [] GenNoiseCurve: serializedVersion: 2 m_Curve: - serializedVersion: 3 time: 0 value: 0 inSlope: -1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 - serializedVersion: 3 time: 1 value: 1 inSlope: 1 outSlope: -1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 ProcessParentCurve: serializedVersion: 2 m_Curve: - serializedVersion: 3 time: 0 value: 0 inSlope: -1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 - serializedVersion: 3 time: 1 value: 1 inSlope: 1 outSlope: -1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 guid: m_storage: d8af6b06-bfff-47fd-869a-fcb4a09abc56 - Name: Stones XOffset1000: 0 XOffset100: 0 XOffset10: 0 XOffset1: 0 YOffset1000: 0 YOffset100: 0 YOffset10: 0 YOffset1: 0 ZOffset: 0 MaxValue: 0.223 PerlinScalar: 18.2 UseAbsVal: 0 GenNoiseType: 1 ProcessParentType: 4 CombineType: 0 ProcessParentVariables: [] Complement: 0 Mute: 0 DoNotProcessDescendants: 0 PCGConfigChildren: [] GenNoiseCurve: serializedVersion: 2 m_Curve: - serializedVersion: 3 time: 0.0076453895 value: -0.20139194 inSlope: 0 outSlope: 0 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 - serializedVersion: 3 time: 0.7651606 value: -0.2052122 inSlope: 0 outSlope: 0 tangentMode: 0 weightedMode: 0 inWeight: 0.33333334 outWeight: 0.5875446 - serializedVersion: 3 time: 0.81492245 value: 0.24654758 inSlope: 1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0.33333334 outWeight: 0.33333334 - serializedVersion: 3 time: 0.84866655 value: 0.7067228 inSlope: 9.893763 outSlope: 9.893763 tangentMode: 0 weightedMode: 0 inWeight: 0.33333334 outWeight: 0.33333334 - serializedVersion: 3 time: 1 value: 1 inSlope: 1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 ProcessParentCurve: serializedVersion: 2 m_Curve: - serializedVersion: 3 time: 0 value: 0 inSlope: -1 outSlope: 1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 - serializedVersion: 3 time: 1 value: 1 inSlope: 1 outSlope: -1 tangentMode: 0 weightedMode: 0 inWeight: 0 outWeight: 0 m_PreInfinity: 2 m_PostInfinity: 2 m_RotationOrder: 4 guid: m_storage: 26de7ffd-1067-4532-9174-b040c231f8df
Procedural Map Overview
How the Map Works
1. Terrain Node (Max 0.212)
- The root height range; everything else adds/subtracts from this.
2. Biomes Node (Perlin 4.1, Max 0.79)
- Generates a noise map from 0 β 1.
- Each child biome only activates in a subrange of that map.
MountainBiome (0.45 β 0.6 slice)
-
Only points where the Biomes noise is between 0.45 and 0.6 contribute to mountains.
-
Combine Multiply β multiplies this mask with the child Perlin noise:
- MountainBase (7.4, Max 0.361)
- MountainDetail (28.4, Max 0.24)
Biomes value β MountainBiome
0.0 βββββββ no
0.45 ββββββ start
0.525 βββββ full
0.6 βββββββ end
0.7 βββββββ no
1.0 βββββββ noHillsBiome ([0 β 0.25 β fade to 0.5])
-
This is a trapezoid/fading mask: full hills from 0 β 0.25, then taper off to 0 at 0.5.
-
Combine Multiply β child nodes inherit the mask:
- HillsBase (8.4, Max 0.263)
- HillDetail (28.9, Max 0.023)
- Stones (18.2, Max 0.223, Thresholded)
Biomes value β HillsBiome
0.0 βββββ full
0.25 ββββ full
0.5 βββββ fade to 0
0.6 βββββ 0
1.0 βββββ 0
Putting it all together
0.0 βββββ Hills
0.25 βββ Hills still full
0.3 βββββ Hills fading, mountains still 0
0.45 ββββ Mountain start
0.5 βββββ Mountain full, hills fading
0.6 βββββ Mountain end
0.7 βββββ Nothing (or minimal)
1.0 βββββ Nothing
Perlin Noise and Max Value Breakdown
1. Terrain (Max: 0.212)
- Top-level terrain node.
- Max: 0.212 β caps overall height/amplitude.
2. Biomes (Perlin: 4.1, Max: 0.79)
- Defines where biomes appear.
- Perlin: 4.1 β frequency of variation (low = smooth, high = choppy).
- Max: 0.79 β amplitude of the biome mask.
3. MountainBiome (Mask: Trapezoid [0.45β0.6], Combine: Multiply)
a. MountainBase (Perlin: 7.4, Max: 0.361)
- Frequency of base mountain noise.
- Max caps base mountain height.
i. MountainDetail (Perlin: 28.4, Max: 0.24)
- Adds fine-grained detail (small rocks/ridges).
- High frequency β tight jagged noise.
4. HillsBiome (Mask: [0β0.25 β fade to 0.5], Combine: Multiply)
a. HillsBase (Perlin: 8.4, Max: 0.263)
- Base hills; slightly higher frequency than mountains.
i. HillDetail (Perlin: 28.9, Max: 0.023)
- Tiny bumps for subtle roughness.
ii. Stones (Perlin: 18.2, Max: 0.223, Thresholded)
- Adds scattered rocky details.
- Thresholded β noise becomes rocks/no rocks.
β Summary
- Perlin value β frequency of noise (low = smooth, high = jagged).
- Max value β amplitude / height / intensity.
- Mask & Combine β controls placement.
- Hierarchy β large features first β small details later.
MountainBiome Slice Explained
Biomes Node Output
The 0.45 here doesnβt directly refer to world height. It refers to the value of the Biomes nodeβs noise output, which is a number between 0 and the Biomes Max (0.79 in your config).
Perlin: 4.1
Max: 0.79-
At each
(x, y)point on the terrain, the Biomes node generates a value:BiomesValue = PerlinNoise(x, y) * 0.79 -
Range:
0 β 0.79 -
This value is not the world height. Itβs a mask / control value that decides where biomes appear.
MountainBiome Slice
Mask: Trapezoid [0.45 β 0.6]-
βActiveβ points are those where:
0.45 β€ BiomesValue β€ 0.6 -
Only these points contribute to mountains.
-
This doesnβt mean the mountains start at height 0.45 in the world. It means the mountain shape will be generated where the Biomes noise falls in that range.
Child Nodes (MountainBase / MountainDetail)
- They have their own Perlin and Max values, which do affect actual height.
- The MountainBiome slice acts like a mask, limiting where the height contributions are applied.
Summary
0.45β0.6β slice of noise values, not height- Height is determined later by the child nodesβ Perlin * Max
Final Result




