Procedural Terrain Generation – Noise – Part 2

It is time for the next part of our Procedural Terrain Generation series. This time we will use noise to generate elevation of terrain!

If you missed the last post about generating a plane for our terrain, you should read it first!

Everyone else, let’s make some noise!

Perlin Noise to be exact. ?

Perlin Noise

Perlin Noise example

Perlin Noise is a pseudo-generated pattern of floating points. In the case of Unity, we have just two dimensions available, but it’s more than enough for now.

In general, function Mathf.PerlinNoise() return values between 0.0f and 1.0f, but we can read in the documentation that it might exceed these values. However, we don’t care that much about it here. ?

Implementation

As a little reminder, I’m going to reuse code from the last post to generate a plane so if you don’t have it yet now it’s time to grab it!

Ready?

Let’s start with adding some parameters for the noise configuration.

using UnityEngine;

/// <summary>
/// Script that generates a plane with width and depth.
/// </summary>
public class PlaneGenerator : MonoBehaviour
{

    ...

    [Header("Noise")]
    // Multiplier for noise.
    [SerializeField]
    private float noisePower = 1;

    // Noise offset.
    [SerializeField]
    private Vector2 noiseOffset;

    // Noise scale.
    [SerializeField]
    private float noiseScale = 1;

    ...

}

With parameters, now we can use PerlinNoise function to add elevation!

using UnityEngine;

/// <summary>
/// Script that generates a plane with width and depth.
/// </summary>
public class PlaneGenerator : MonoBehaviour
{
    
    ...

    /// <summary>
    /// Method which generates plane.
    /// </summary>
    private void GeneratePlane()
    {
        ...

        // Defining vertices.
        Vector3[] vertices = new Vector3[(width + 1) * (depth + 1)];

        int i = 0;
        for (int d = 0; d <= depth; d++)
        {
            for (int w = 0; w <= width; w++)
            {
                // Setting vertice position.
                vertices[i] = new Vector3(w, 0, d) - new Vector3(width / 2f, 0, depth / 2f);

                // Adding elevation from perlin noise.
                float noiseXCoord = noiseOffset.x + w / (float)width * noiseScale;
                float noiseYCoord = noiseOffset.y + d / (float)depth * noiseScale;
                vertices[i].y = (Mathf.PerlinNoise(noiseXCoord, noiseYCoord) - 0.5f) * noisePower;

                i++;
            }
        }

        ...

    }

    ...

}

Great! Now let’s see if it works!

Elevation on our terrain!

Niiiiiiceee ?

But it can be better! Right now to see changes we have to stop editor, make changes, and enter play mode again. That’s too much!

I want to play with these values in the editor as long as we are in Play mode!

And we can do it simply by creating an editor script that will call update on the generator. But first, let’s add UpdatePlane method.

using UnityEngine;

/// <summary>
/// Script that generates a plane with width and depth.
/// </summary>
public class PlaneGenerator : MonoBehaviour
{
    ...

#if UNITY_EDITOR
    /// <summary>
    /// This method updates / generates new plane.
    /// Called from editor script on change.
    /// </summary>
    public void UpdatePlane()
    {
        GeneratePlane();
    }
#endif

}

I wanted to create a method that will work only in the editor. That’s why I used conditional compiling.

Now we have to create an editor script, which also is even simpler!

using UnityEngine;
using UnityEditor;

/// <summary>
/// This simple editor script regenerates plane when change is made.
/// </summary>
[CustomEditor(typeof(PlaneGenerator))]
public class PlaneGeneratorEditor : Editor
{
    /// <summary>
    /// Unity method called to draw inspector.
    /// </summary>
    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();

        // Reference to the plane generator script.
        var generator = target as PlaneGenerator;

        // Regenerating plane only if we are in Play mode.
        if (Application.isPlaying)
        {
            generator.UpdatePlane();
        }
    }
}

See? I told you. ?

You can refresh that subject with my other post about it.

With that, we can finally mess around in Play mode and see how the plane is changing! ?

Updating mesh!

What do you think about it? Did you mess with noises before? Let me know in the comment section below!

If you want to get notified on future content, sign up for the newsletter!

As always, the whole project is available at my public repository. ?

And I hope to see you next time! ?

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x