3

I'm trying to create procedural terrain generator using perlin noise and marching cubes in unity. It was working until I switched from creating a height map to making it into a 3d array. Then, whenever I clicked on play, unity opened a dialog box with Application.EnterPlayMode written which would not go away and never entered play mode. Everything stops responding when it happens and they only way to stop it is to kill it in task manager.

The script in question is below:

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

public class Noise : MonoBehaviour
{
    //Determines whether to show debug values
    public bool debug = false;

    //Determines flatness of the terrain
    public float noiseScale = 0.5f;

    //Type of perlin noise to use
    public enum PerlinNoise {
        twoD,
        threeD
    };
    public PerlinNoise perlinNoiseDimension = PerlinNoise.twoD;

    //To return noise data after all calculations
    public float[,,] getTerrainData(int x, int y, int z)
    {
        float[,,] terrainData = new float[x, y, z];

        if(perlinNoiseDimension == PerlinNoise.twoD)
        {
            terrainData = PerlinNoise2D(x, y, z, noiseScale);
        }
        return terrainData;
    }

    //Determine noise values using 2D Perlin noise
    private float[,,] PerlinNoise2D(int x, int y, int z, float noiseScale)
    {
        float[,,] voxelHeights = new float[x, y, z];

        if (debug)
        {
            Debug.Log("Heightmap");
        }

        //Origin points to sample from
        float xOrg = Random.Range(0.0f, 0.9999999f);
        float yOrg = Random.Range(0.0f, 0.9999999f);

        for (int currentx = 0; currentx < x; currentx++)
        {
            for (int currenty = 0; currenty < y; currenty++)
            {
                //Convert Values to Fractions
                float xCoord = (float)currentx / (x * noiseScale) + xOrg;
                float yCoord = (float)currenty / (y * noiseScale) + yOrg;

                float height = Mathf.PerlinNoise(xCoord, yCoord) * z;

                for(int currentz = 0; currentz <= height; z++)
                {
                    voxelHeights[currentx, currenty, currentz] = 1;
                }

                if (debug)
                {
                    Debug.Log("Height = " + height + ", X = " + currentx + ", Y = " + currenty + ", X Coord = " + xCoord + ", Y Coord = " + yCoord);
                }
            }

        }
        return voxelHeights;
    }
}

An image of what it shows is below:

The error

Cardstdani
  • 4,999
  • 3
  • 12
  • 31
Rattandeep
  • 75
  • 1
  • 2
  • 8
  • derHugo's answer looks pretty correct to me. I will add that I do not recommed Unity's Mathf.PerlinNoise function. Perlin may be the iconic noise name, but it produces visible grid alignment and is probably rarely the best choice anymore. I would look for a good simplex noise implementation to import. That way your mountains won't all be aligned 45 and 90 degrees. – KdotJPG Jul 31 '20 at 13:40

1 Answers1

6

You are causing a never ending loop in

for(int currentz = 0; currentz <= height; z++)
{
    voxelHeights[currentx, currenty, currentz] = 1;
}

here you are increasing z++ but your loop condition is on currentz <= height. Within the loop you never update the value of currentz nor the value of height so your loop never finishes.

Due to the usage of indices it should probably rather have been

for(int currentz = 0; currentz <= height; currentz++)
{
    voxelHeights[currentx, currenty, currentz] = 1;
}

However not sure how the height comes into play here because I would expect it rather to look somewhat like e.g.

for(int currentz = 0; currentz < z; currentz++)
{
    voxelHeights[currentx, currenty, currentz] = height;
}

That seems to make more sense to me.

derHugo
  • 83,094
  • 9
  • 75
  • 115