[RELEASED] PixelSurface: Efficient Destructible 2D Terrain

OK, here’s a little example of random terrain generation. I was originally thinking “caves,” but what came out of it is more like “platforms,” and it’s so cool that I just ran with it. :slight_smile:

Here’s the code:

using UnityEngine;
using UnityEngine.Events;
using System.Collections.Generic;
using PixSurf;

public class RandomCaves : MonoBehaviour {
    public Vector2 noiseOrigin;
    public Vector2 noiseScale = new Vector2(8, 10);
    public float threshold = 0.5f;
    public Color clearColor = Color.clear;
    public Color rockColor = Color.gray;
    public Color grassColor = Color.green;
   
    void Start() {
        GenerateCaves();
        GrowGrass();
    }

    public void GenerateCaves() {
        PixelSurface surf = GetComponent<PixelSurface>();
        surf.Reset();
        Vector2 surfSize = new Vector2(surf.totalWidth, surf.totalHeight);
        for (int y=0; y<surf.totalHeight; y++) {
            for (int x=0; x<surf.totalWidth; x++) {
                float sampleX = noiseOrigin.x + x * noiseScale.x / surfSize.x;
                float sampleY = noiseOrigin.y + y * noiseScale.y / surfSize.y;
                float sample = Mathf.PerlinNoise(sampleX, sampleY);
                Color c = (sample < threshold ? clearColor : rockColor);
                surf.SetPixel(x, y, c);
            }
        }
        Debug.Log("Set " + surf.totalWidth +"x" + surf.totalHeight);
    }
   
    public void GrowGrass() {
        PixelSurface surf = GetComponent<PixelSurface>();
        for (int x=0; x<surf.totalWidth; x++) {
            int grassDepth = 0;
            for (int y=surf.totalHeight-1; y>=0; y--) {
                if (surf.GetPixel(x, y) == clearColor) {
                    grassDepth = Random.Range(1,3) + Random.Range(1,3);
                } else if (grassDepth > 0) {
                    surf.SetPixel(x, y, grassColor);
                    grassDepth--;
                }
            }
        }
    }
}

To try it out for yourself:

  • Make a new scene.
  • Create a new empty GameObject, add a PixelSurface component, and configure it as shown in the image above.
  • Attach the above RandomCaves script.
  • Run.

There is of course a lot that could be done to extend this script and make it better, such as picking slightly different shades based on the gradient of the noise function, adding random rocks within the dirt, making the grass stick up a bit on top, etc.

And of course we’re only doing one sample of the noise function here; typically you can get more interesting & detailed results by sampling it multiple times, at different scales, and just adding them together. But I rather liked the look of the smooth platforms & blobs produced by this simple method.

3 Likes