So this “bug” have annoyed me for a while now and I keep scratching my head over why it happens. My thoughts are that it may have something to do with the “SetNeighbors” method, as if I comment that out it doesn’t crash.
So I was wondering if anyone else have this issues and what I should do to avoid this from happening?
My code for dynamic terrain adding/deletion is here:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class ChunkLoader : MonoBehaviour
{
int LoadDistance = 5;
int Center { get { return (LoadDistance - 1) / 2; } }
int ChunkSize = 512;
List<List<GameObject>> Chunks = new List<List<GameObject>>();
Terrain lt;
Terrain rt;
Terrain tt;
Terrain bt;
[SerializeField]
GameObject Player;
// Use this for initialization
void Start ()
{
for (int i = 0; i < LoadDistance; i++)
{
List<GameObject> lgo = new List<GameObject>();
for (int j = 0; j < LoadDistance; j++)
{
GameObject go = new GameObject();
go.AddComponent<SimpleTerrainGenerator>();
go.transform.position = new Vector3(((((LoadDistance - 1) / 2) - LoadDistance) + j + 1) * ChunkSize, 0, (((LoadDistance - 1) / 2 - LoadDistance) + i + 1) * ChunkSize);
go.name = go.name + "[" + (j - Center) + ";" + (i - Center) + "]";
lgo.Add(go);
go.GetComponent<SimpleTerrainGenerator>().Starter();
}
Chunks.Add(lgo);
}
for (int i = 0; i < LoadDistance; i++)
{
for (int j = 0; j < LoadDistance; j++)
{
if (i != 0)
{
bt = Chunks[i - 1][j].GetComponent<Terrain>();
TerrainTools.StitchTerrains(bt, Chunks[i][j].GetComponent<Terrain>(), 64, 0, 20);
}
if (i != LoadDistance - 1)
{
tt = Chunks[i + 1][j].GetComponent<Terrain>();
TerrainTools.StitchTerrains(tt, Chunks[i][j].GetComponent<Terrain>(), 64, 0, 20);
}
if (j != 0)
{
lt = Chunks[i][j - 1].GetComponent<Terrain>();
TerrainTools.StitchTerrains(lt, Chunks[i][j].GetComponent<Terrain>(), 64, 0, 20);
}
if (j != LoadDistance - 1)
{
rt = Chunks[i][j + 1].GetComponent<Terrain>();
TerrainTools.StitchTerrains(rt, Chunks[i][j].GetComponent<Terrain>(), 64, 0, 20);
}
Chunks[i][j].GetComponent<Terrain>().SetNeighbors(lt, tt, rt, bt);
Chunks[i][j].GetComponent<Terrain>().Flush();
bt = null;
tt = null;
lt = null;
rt = null;
}
}
}
// Update is called once per frame
void Update()
{
if (Player.transform.position.z < Chunks[Center - 1][Center].transform.position.z + (ChunkSize / 2))
{
AddColumnBack();
DeleteColumnFront();
}
if (Player.transform.position.z > Chunks[Center + 1][Center].transform.position.z - (ChunkSize / 2))
{
AddColumnFront();
DeleteColumnBack();
}
if (Player.transform.position.x < Chunks[Center][Center - 1].transform.position.x + (ChunkSize / 2))
{
AddRowBack();
DeleteRowFront();
}
if (Player.transform.position.x > Chunks[Center][Center + 1].transform.position.x - (ChunkSize / 2))
{
AddRowFront();
DeleteRowBack();
}
}
void AddColumnFront()
{
Vector3 vec = Chunks[Chunks.Count - 1][Center].transform.position;
List<GameObject> lgo = new List<GameObject>();
int c = -(Center * ChunkSize);
for (int i = 0; i < Chunks.Count; i++)
{
GameObject go = new GameObject();
go.transform.position = new Vector3(vec.x + c, 0, vec.z + ChunkSize);
go.AddComponent<SimpleTerrainGenerator>();
go.name = go.name + "[" + go.transform.position.x / ChunkSize + ";" + go.transform.position.z / ChunkSize + "]";
lgo.Add(go);
go.GetComponent<SimpleTerrainGenerator>().Starter();
c += ChunkSize;
}
Chunks.Add(lgo);
}
void AddColumnBack()
{
Vector3 vec = Chunks[0][Center].transform.position;
List<GameObject> lgo = new List<GameObject>();
int c = -(Center * ChunkSize);
for (int i = 0; i < Chunks.Count; i++)
{
GameObject go = new GameObject();
go.transform.position = new Vector3(vec.x + c, 0, vec.z - ChunkSize);
go.AddComponent<SimpleTerrainGenerator>();
go.name = go.name + "[" + go.transform.position.x / ChunkSize + ";" + go.transform.position.z / ChunkSize + "]";
lgo.Add(go);
go.GetComponent<SimpleTerrainGenerator>().Starter();
c += ChunkSize;
}
Chunks.Insert(0, lgo);
}
void AddRowFront()
{
Vector3 vec = Chunks[Center][Chunks[1].Count - 1].transform.position;
int c = -(Center * ChunkSize);
foreach (List<GameObject> lgo in Chunks)
{
GameObject go = new GameObject();
go.transform.position = new Vector3(vec.x + ChunkSize, 0, vec.z + c);
go.AddComponent<SimpleTerrainGenerator>();
go.name = go.name + "[" + go.transform.position.x / ChunkSize + ";" + go.transform.position.z / ChunkSize + "]";
go.GetComponent<SimpleTerrainGenerator>().Starter();
lgo.Add(go);
c += ChunkSize;
}
}
void AddRowBack()
{
Vector3 vec = Chunks[Center][0].transform.position;
int c = -(Center * ChunkSize);
foreach (List<GameObject> lgo in Chunks)
{
GameObject go = new GameObject();
go.transform.position = new Vector3(vec.x - ChunkSize, 0, vec.z + c);
go.AddComponent<SimpleTerrainGenerator>();
go.name = go.name + "[" + go.transform.position.x / ChunkSize + ";" + go.transform.position.z / ChunkSize + "]";
go.GetComponent<SimpleTerrainGenerator>().Starter();
lgo.Insert(0, go);
c += ChunkSize;
}
}
void DeleteColumnFront()
{
for (int i = 0; i < Chunks[Chunks.Count - 1].Count; i++)
{
GameObject.Destroy(Chunks[Chunks.Count - 1][i].gameObject);
}
Chunks.RemoveAt(Chunks.Count - 1);
}
void DeleteColumnBack()
{
for (int i = 0; i < Chunks[0].Count; i++)
{
GameObject.Destroy(Chunks[0][i].gameObject);
}
Chunks.RemoveAt(0);
}
void DeleteRowFront()
{
foreach (List<GameObject> lgo in Chunks)
{
GameObject.Destroy(lgo[lgo.Count - 1]);
lgo.RemoveAt(lgo.Count - 1);
}
}
void DeleteRowBack()
{
foreach (List<GameObject> lgo in Chunks)
{
GameObject.Destroy(lgo[0]);
lgo.RemoveAt(0);
}
}
}
All forgot to mention the generator, but it pretty much just create the terrain and makes all the setup and such:
using UnityEngine;
using System;
using System.Collections;
using LibNoise.Unity;
using LibNoise.Unity.Generator;
using LibNoise.Unity.Operator;
public class SimpleTerrainGenerator : MonoBehaviour
{
public GameObject[] go;
public int[] percentage;
public int seed;
//public HeightMap HeightMap;
//public BiomeMap BiomeMap;
public Terrain ThisTerrain;
public Terrain TerTop;
public Terrain TerLeft;
public Terrain TerRight;
public Terrain TerBottom;
// Use this for initialization
public void Starter()
{
Terrain terrrain = this.gameObject.AddComponent<Terrain>();
TerrainData terrraindata = terrrain.terrainData = new TerrainData();
terrrain.terrainData.heightmapResolution = 256;
terrrain.terrainData.size = new Vector3(512, 512, 512);
TerrainCollider terrraincollider = this.gameObject.AddComponent<TerrainCollider>();
terrraincollider.terrainData = terrraindata;
float fl = UnityEngine.Random.Range(0.0f, 100000.0f);
//PrepareTerrain();
float[,] h = new float[terrraindata.heightmapResolution, terrraindata.heightmapResolution];
Vector3 gopos = terrrain.transform.position;
float cwidth = terrraindata.size.x;
int resolution = terrraindata.heightmapResolution;
float[,] hmap = new float[resolution, resolution];
double yoffset = 0 - (gopos.x / cwidth);
double xoffset = (gopos.z / cwidth);
Noise2D tmpNoiseMap = new Noise2D(resolution, resolution, new Perlin(0.25, 1, 0.5, 4, 0, QualityMode.High));
tmpNoiseMap.GeneratePlanar(xoffset, (xoffset) + (1f / resolution) * (resolution + 1), -yoffset, (-yoffset) + (1f / resolution) * (resolution + 1));
for (int hY = 0; hY < resolution; hY++)
{
for (int hX = 0; hX < resolution; hX++)
{
hmap[hX, hY] = ((tmpNoiseMap[hX, hY] * 0.5f) + 0.5f) * 1;
}
}
terrrain.GetComponent<Terrain>().terrainData.SetHeights(0, 0, hmap);
}
}