Why is my Perlin noise not lining up properly?

51 Views Asked by At

I have two scripts, one attached to a prefab with a mesh filterer and mesh renderer that creates Perlin noise meshes (GenTerrain.cs), another attached to an empty game object that handles terrain chunk spawning (TerrainManager.cs). Perlin noise generated for spawned game objects does not line up. It creates new Perlin noise terrain object when player position is far enough from the old tile.

GenTerrain.cs:

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

public class GenTerrain : MonoBehaviour
{
    public int width = 10;
    public int height = 10;
    public float scale = 20.0f;
    public float xOffset = 0f;
    public float zOffset = 0f;

    [Header("Perlin Noise Settings")]
    public int numOctaves = 4;
    public float amplitude = 2f;
    public float persistence = 0.5f;

    private Mesh mesh;
    private Vector3[] vertices;
    private int[] triangles;

    public void GenerateTerrain()
    {
        mesh = new Mesh();
        GetComponent<MeshFilter>().mesh = mesh;

        vertices = new Vector3[(width + 1) * (height + 1)];

        int i = 0;
        for (int z = 0; z <= height; z++)
        {
            for (int x = 0; x <= width; x++)
            {
                float xCoord = (float)x / width * scale;
                float zCoord = (float)z / height * scale;
                float y = CalculatePerlinNoise(xCoord + xOffset, zCoord + zOffset);
                vertices[i] = new Vector3(x, y, z);
                i++;
            }
        }

        triangles = new int[width * height * 6];

        int vert = 0;
        int tris = 0;

        for (int z = 0; z < height; z++)
        {
            for (int x = 0; x < width; x++)
            {
                triangles[tris + 0] = vert;
                triangles[tris + 1] = vert + width + 1;
                triangles[tris + 2] = vert + 1;
                triangles[tris + 3] = vert + 1;
                triangles[tris + 4] = vert + width + 1;
                triangles[tris + 5] = vert + width + 2;

                vert++;
                tris += 6;
            }
            vert++;
        }

        mesh.Clear();
        mesh.vertices = vertices;
        mesh.triangles = triangles;
        mesh.RecalculateNormals();
        mesh.RecalculateBounds();
    }

    private float CalculatePerlinNoise(float x, float z)
    {
        float y = 0f;
        for (int o = 0; o < numOctaves; o++)
        {
            float frequency = Mathf.Pow(2, o);
            float amplitudeFactor = Mathf.Pow(persistence, o);
            y += Mathf.PerlinNoise(x * frequency, z * frequency) * amplitude * amplitudeFactor;
        }
        return y;
    }
}

TerrainManager.cs:

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

public class TerrainManager : MonoBehaviour
{
    public GameObject chunk;
    public Transform player;
    private Dictionary<Vector3,GameObject> chunks = new Dictionary<Vector3, GameObject>();

    void Update()
    {
        Vector3 roundedPlayerPos = RoundToNearestTen(player.position);
        if (!chunks.ContainsKey(roundedPlayerPos)) {
            Debug.Log("chunks");
            GameObject currChunk = Instantiate(chunk, roundedPlayerPos, Quaternion.identity);
            GenTerrain scripting = currChunk.GetComponent<GenTerrain>();

            scripting.xOffset = roundedPlayerPos.x;
            scripting.zOffset = roundedPlayerPos.z;
            scripting.GenerateTerrain();
            chunks.Add(roundedPlayerPos, currChunk);
        }
    }

    Vector3 RoundToNearestTen(Vector3 a) {
        return new Vector3(
            Mathf.RoundToInt(a.x/10)*10,
            Mathf.RoundToInt(a.y/10)*10,
            Mathf.RoundToInt(a.z/10)*10
            );
    }
}

Terrain prefab has width of 10, height of 10, scale of 4, 1 octave, amplitude of 4, and 0 persistence:

enter image description here

0

There are 0 best solutions below