Adding caves to Perlin Noise generation?

Hi,

I have a procedural perlin noise generation in my game that generates the world in chunks and I want to add caves to the generation, could someone help with that?

Code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class level_gen : MonoBehaviour {

    //Basic blocks
    public GameObject moonrockTile;
    public GameObject moonstoneTile;
    public GameObject mudTile;
    public GameObject moonsandTile;

    //Ores
    public GameObject tileGold;
    public GameObject tileCopper;
    public GameObject tileSilver;

    public int width;
    public float heightMultiplier;
    public int heightAddition;

    public float smoothness;

    public float seed;

    public float chanceGold;
    public float chanceCopper;
    public float chanceSilver;

    void Start ()
    {
        Generate ();
        seed = Random.Range (-10000, 10000);
    }

    public void Generate ()
    {
        for(int i = 0; i < width; i++)
        {
            int h = Mathf.RoundToInt (Mathf.PerlinNoise (seed, (i +transform.position.x) / smoothness) * heightMultiplier) + heightAddition;

            for (int j = 0; j < h; j++)
            {
                GameObject selectedTile;

                //Layers of tiles here:
                if (j < h - 8)
                {
                    selectedTile = moonstoneTile;
                }
                else if (j < h -4)
                {
                    selectedTile = mudTile;
                }
                else if (j < h - 2)
                {
                    selectedTile = moonsandTile;
                }
                else
                {
                    selectedTile = moonrockTile;
                }

                //Spawn new tiles and add to Generate gameobject
                GameObject newTile = Instantiate (selectedTile, Vector3.zero, Quaternion.identity) as GameObject;

                newTile.transform.parent = this.gameObject.transform;
                newTile.transform.localPosition = new Vector3 (i, j);
            }
        }

        GenOre ();
    }

    public void GenOre()
    {
        foreach(GameObject t in GameObject.FindGameObjectsWithTag("tile_stone"))
        {
            if (t.transform.parent == this.gameObject.transform)
            {
                float r = Random.Range (0f, 100f);
                GameObject selectedTile = null;

                if (r < chanceGold)
                {
                    selectedTile = tileGold;
                }
                else if (r < chanceSilver)
                {
                    selectedTile = tileSilver;
                }
                else if(r < chanceCopper)
                {
                    selectedTile = tileCopper;
                }

                if(selectedTile != null)
                {
                    GameObject newResourceTile = Instantiate (selectedTile, t.transform.position, Quaternion.identity) as GameObject;
                    newResourceTile.transform.parent = transform;
                    Destroy (t);
                }
            }
        }
    }
}

Also a quick question; How would I create a black fade on tiles far away like Terraria

Example: Imgur: The magic of the Internet

Help would be really appreciated!

Thanks peeps!

Dean

Generate a second field of perlin noise and subtract it from the first

Hi,

thanks for the reply, for the cave generation or the black fade (lighting) on the tiles?

Do something like this

    float noiseValue = Mathf.PerlinNoise(xFloat, yFloat);
                if (noiseValue > .6f)
                     // it's a cave

Ah okay, im not well known with purlin noise, I have the script below to make the terrain, so regarding your post above how would I implement that into my script below?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class level_gen : MonoBehaviour {

    //Basic blocks
    public GameObject moonrockTile;
    public GameObject moonstoneTile;
    public GameObject mudTile;
    public GameObject moonsandTile;

    //Ores
    public GameObject tileGold;
    public GameObject tileCopper;
    public GameObject tileSilver;

    public int width;
    public float heightMultiplier;
    public int heightAddition;

    public float smoothness;

    public float seed;

    public float chanceGold;
    public float chanceCopper;
    public float chanceSilver;

    void Start ()
    {
        Generate ();
        seed = Random.Range (-10000, 10000);
    }

    public void Generate ()
    {
        for(int i = 0; i < width; i++)
        {
            int h = Mathf.RoundToInt (Mathf.PerlinNoise (seed, (i +transform.position.x) / smoothness) * heightMultiplier) + heightAddition;

            for (int j = 0; j < h; j++)
            {
                GameObject selectedTile;

                //Layers of tiles here:
                if (j < h - 8)
                {
                    selectedTile = moonstoneTile;
                }
                else if (j < h -4)
                {
                    selectedTile = mudTile;
                }
                else if (j < h - 2)
                {
                    selectedTile = moonsandTile;
                }
                else
                {
                    selectedTile = moonrockTile;
                }

                //Spawn new tiles and add to Generate gameobject
                GameObject newTile = Instantiate (selectedTile, Vector3.zero, Quaternion.identity) as GameObject;

                newTile.transform.parent = this.gameObject.transform;
                newTile.transform.localPosition = new Vector3 (i, j);
            }
        }



        GenOre ();
    }

    public void GenOre()
    {
        foreach(GameObject t in GameObject.FindGameObjectsWithTag("tile_stone"))
        {
            if (t.transform.parent == this.gameObject.transform)
            {
                float r = Random.Range (0f, 100f);
                GameObject selectedTile = null;

                if (r < chanceGold)
                {
                    selectedTile = tileGold;
                }
                else if (r < chanceSilver)
                {
                    selectedTile = tileSilver;
                }
                else if(r < chanceCopper)
                {
                    selectedTile = tileCopper;
                }

                if(selectedTile != null)
                {
                    GameObject newResourceTile = Instantiate (selectedTile, t.transform.position, Quaternion.identity) as GameObject;
                    newResourceTile.transform.parent = transform;
                    Destroy (t);
                }
            }
        }
    }
}

Mathf.PerlinNoise returns values between 0 and 1. Rounding it to integer does not make sense. If you have no idea what you are doing start here.