Мой скрипт случайным образом генерирует воксельный ландшафт из трехмерного шума Перлина. Затем он устанавливает случайный материал для каждого куба. Я начал с существующего скрипта и переместил все вокруг, чтобы заставить его делать то, что я хочу, так что это не очень хорошо. (камера сцены или игровая камера) перемещается на некоторое расстояние от куба, материал кажется отсутствующим. Это недалеко / далеко, материалы исчезают через определенные промежутки времени. Если в одной камере отсутствует материал, в других камерах он выглядит нормально. Сначала это происходит в радиусе вокруг камеры, затем все расстояния после этого несовместимы. При каждом удалении приращения расстояние между приращениями увеличивается.
Это касается любого куба, созданного в первом поколении (из Start ()). Любой другой куб, созданный (из Update ()), не изменяется. Не имеет значения, сколько кубиков сгенерировано.
Ошибка в представлении игры
Ошибка в представлении сцены
void Start()
{
Destroy(GameObject.Find("Meshys"));//destroy parent gameobject as well as children.
foreach (Mesh m in meshes)//meshes still exist even though they aren't in the scene anymore. destroy them so they don't take up memory.
Destroy(m); //I don't know if this even works anymore
Generate();
}
[SerializeField]
private GameObject blockPrefab;//use a unit cube (1x1x1 like unity's default cube)
[SerializeField]
private int chunkSize = 50;//Size of area to generate
[SerializeField]
private float noiseScale = .05f;
[SerializeField, Range(0, 1)]
private float threshold = .5f;//Perlin noise threshold to generate a cube
[SerializeField]
private Material material_1;
[SerializeField]
private Material material_2;
[SerializeField]
private Material material_3;
[SerializeField]
private Material material_4;
[SerializeField]
private Material material_5;
[SerializeField]
private float chooseMesh;
[SerializeField]
private bool sphere = false;
float timeStuff = 0f;
float timeStuff_2 = 0f;
int startupTime;
float startupTime_2;
private List<Mesh> meshes = new List<Mesh>();//used to avoid memory issues
public float offsetX = 100f;
public float offsetY = 100f;
public float offsetZ = 100f;
public float scale = 20f;
private void Generate()
{
float startTime = Time.realtimeSinceStartup;
#region Create Mesh Data
List<CombineInstance> blockData = new List<CombineInstance>();//this will contain the data for the final mesh
Transform container = new GameObject("Meshys").transform;//create container object
//go through each block position
for (int x = 0; x < chunkSize; x++)
{
for (int y = 0; y < chunkSize; y++)
{
for (int z = 0; z < chunkSize; z++)
{
float noiseValue = Perlin3D(x * noiseScale, y * noiseScale, z * noiseScale);//get value of the noise at given x, y, and z.
if (noiseValue >= threshold)
{//is noise value above the threshold for placing a block?
//ignore this block if it's a sphere and it's outside of the radius (ex: in the corner of the chunk, outside of the sphere)
//distance between the current point with the center point. if it's larger than the radius, then it's not inside the sphere.
float raduis = chunkSize / 2;
if (sphere && Vector3.Distance(new Vector3(x, y, z), Vector3.one * raduis) > raduis)
continue;
GameObject blockMesh = Instantiate(blockPrefab, Vector3.zero, Quaternion.identity);//create a unit cube and store the mesh from it
MeshFilter blockMeshMesh = blockMesh.GetComponent<MeshFilter>();
MeshRenderer mr = blockMesh.GetComponent<MeshRenderer>();//Get mesh renderer component
blockMesh.transform.position = new Vector3(x, y, z);//move the unit cube to the intended position
chooseMesh = UnityEngine.Random.Range(0f, 1000f);
//Randomly decide a material for the cube - testing for different items with different rarities
if (chooseMesh >= 0f && chooseMesh < 500f)
{
mr.material = material_1;//set material to avoid evil pinkness of missing texture
}
else if (chooseMesh >= 500f && chooseMesh < 750f)
{
mr.material = material_2;
}
else if (chooseMesh >= 750f && chooseMesh < 875f)
{
mr.material = material_3;
}
else if (chooseMesh >= 875f && chooseMesh < 937.5f)
{
mr.material = material_4;
}
else
{
mr.material = material_5;
}
CombineInstance ci = new CombineInstance
{//copy the data off of the unit cube
mesh = blockMeshMesh.sharedMesh,
transform = blockMesh.transform.localToWorldMatrix,
};
blockData.Add(ci);//add the data to the list
}
}
}
}
//Destroy(blockMesh.gameObject);//original unit cube is no longer needed. we copied all the data we need to the block list. - moved this elsewhere
#endregion
#region Separate Mesh Data
//divide meshes into groups of 65536 vertices. Meshes can only have 65536 vertices so we need to divide them up into multiple block lists.
List<List<CombineInstance>> blockDataLists = new List<List<CombineInstance>>();//we will store the meshes in a list of lists. each sub-list will contain the data for one mesh. same data as blockData, different format.
int vertexCount = 0;
blockDataLists.Add(new List<CombineInstance>());//initial list of mesh data
for (int i = 0; i < blockData.Count; i++)
{//go through each element in the previous list and add it to the new list.
vertexCount += blockData[i].mesh.vertexCount;//keep track of total vertices
if (vertexCount > 65536)
{//if the list has reached it's capacity. if total vertex count is more then 65536, reset counter and start adding them to a new list.
vertexCount = 0;
blockDataLists.Add(new List<CombineInstance>());
i--;
}
else
{//if the list hasn't yet reached it's capacity. safe to add another block data to this list
blockDataLists.Last().Add(blockData[i]);//the newest list will always be the last one added
}
}
#endregion
#region Create Mesh
//the creation of the final mesh from the data.
foreach (List<CombineInstance> data in blockDataLists)
{//for each list (of block data) in the list (of other lists)
GameObject g2 = new GameObject("Meshy");//create gameobject for the mesh
MeshFilter mf2 = g2.AddComponent<MeshFilter>();//add mesh component
MeshRenderer mr2 = g2.AddComponent<MeshRenderer>();//add mesh renderer component
g2.transform.parent = container;//set parent to the container we just made
mf2.mesh.CombineMeshes(data.ToArray());//set mesh to the combination of all of the blocks in the list
meshes.Add(mf2.mesh);//keep track of mesh so we can destroy it when it's no longer needed
g2.AddComponent<MeshCollider>().sharedMesh = mf2.sharedMesh;//setting colliders takes more time
/*
mr.material = material;//set material to avoid evil pinkness of missing texture
This is old but I kept it here in case I needed it again
*/
}
#endregion
//Debug.Log("Loaded in " + (Time.realtimeSinceStartup - startTime) + " Seconds.");
}
void Update()
{
int startupTime = Convert.ToInt32(Time.realtimeSinceStartup);
float startupTime_2 = startupTime;
float timeStuff = startupTime_2 / 60f;
Debug.Log(startupTime);
Debug.Log(timeStuff);
float timeStuff_2 = timeStuff % 10;//Time in minutes to wait between generations.
Debug.Log(timeStuff_2);
//Regenerate terrain after time delay
if (timeStuff_2 == 0)
{
Destroy(GameObject.Find("Meshys"));//destroy parent gameobject as well as children.
Destroy(GameObject.Find("Cube(Clone)"));
foreach (Mesh m in meshes)//meshes still exist even though they aren't in the scene anymore. destroy them so they don't take up memory.
Destroy(m);
Generate();
}
}
//dunno how this works. copied it from somewhere.
float Perlin3D(float x, float y, float z)
{
offsetX = UnityEngine.Random.Range(0f, 10f);
offsetY = UnityEngine.Random.Range(0f, 10f);
offsetZ = UnityEngine.Random.Range(0f, 10f);
float xCoord = (float)x / 2048 + offsetX;
float yCoord = (float)y / 2048 + offsetY;
float zCoord = (float)z / 2048 + offsetZ;
//Don't know what I did here but this makes it random and broken
float ab = Mathf.PerlinNoise(xCoord, yCoord);
float bc = Mathf.PerlinNoise(yCoord, zCoord);
float ac = Mathf.PerlinNoise(xCoord, zCoord);
float ba = Mathf.PerlinNoise(yCoord, xCoord);
float cb = Mathf.PerlinNoise(zCoord, yCoord);
float ca = Mathf.PerlinNoise(zCoord, xCoord);
float abc = ab + bc + ac + ba + cb + ca;
return abc / 6f;
}
Этот сценарий применяется к пустому объекту gameObject. Понятия не имею, что происходит. Будем признательны за любые указатели, где искать.