Performance Efficient Way To Make Voxel Terrain With Cubes?
Currently I'm trying to make a procedurally generated world with voxels, akin to Minecraft, however I don't want to use textures and like the look of having a certain color on the entire cube but just at darker or lighter shades. At the moment, I have a nice script setup that will use perlin noise to make the terrain and have it set so that the height on the perlin noise will change the shade of the color.
This works fine and all, however the problem begins when I try to generate any large size of terrain in. It will go down to just about 10-15 frames when looking at all of the cubes and when I turn away from it and look out onto the sky box, it goes to about 40-60 frames. Same thing happens when I look directly down at my feet and only see a few cubes.
The issue is obviously the cubes being very performance intensive since there are so many. I think it would also help to know that this is only an upper layer of terrain as well. Just grass, since in my game you won't be digging down or anything like that.
My question is how to make this terrain efficiently while keeping the same idea. I've looked at tutorials on how to maybe optimize voxel type stuff, but most of it is trying to recreate Minecraft which is not what I'm going for.
So yeah, if anyone has any ideas on how I could fix the frame rate issue, I would gladly appreciate it. I'll leave my code for the terrain generation right here:
using UnityEngine;
using System.Collections;
public class TerrainGenerator : MonoBehaviour {
public GameObject Block;
public float Scale = 7.00f;
public int Size = 50;
public float heightOffset = 1.5f;
public bool EnableHeight = true;
public float scaleMod = 5f;
public bool Move = false;
public int Seed;
TerrainOptimization optimization;
void Awake () {
FormTerrain ();
//Set the seed up properly later
//Seed = Random.Range(1,99999);
}
void FormTerrain(){
for(int X = 0; X < Size; X++) {
for(int Z = 0; Z < Size; Z++) {
GameObject C = Instantiate(Block, new Vector3(X, 0, Z), Quaternion.identity) as GameObject;
C.transform.parent = transform;
optimization = C.GetComponent<TerrainOptimization> ();
}
}
}
void Update ()
{
UpdateTransform ();
}
void UpdateTransform()
{ foreach (Transform Child in transform)
{ float Height = Mathf.PerlinNoise(Child.transform.position.x/Scale, Child.transform.position.z/Scale);
SetMatColor(Child, Height);
if (EnableHeight == true)
{
ApplyHeight(Child, Height);
}
}
}
void SetMatColor(Transform Child, float Height)
{
foreach (Renderer r in Child.GetComponentsInChildren<Renderer>()) {
r.material.color = new Color (0,1 * Height,0,1 * Height);
}
}
void ApplyHeight(Transform Child, float Height)
{ int YValue = Mathf.RoundToInt (Height * scaleMod);
Vector3 NewVec3 = new Vector3 (Child.transform.position.x, YValue, Child.transform.position.z);
Child.transform.position = NewVec3;
}
}
This is what the script creates:
Answer by LightSlayer5 · Aug 01, 2017 at 04:23 AM
Okay, I seem to have found the problem. So it didn't seem to have been the cubes lagging, but it was me changing the color of the material constantly and making new materials every frame, which Unity didn't seem to like.
So what I did was (for anyone wondering,) was I moved the setting of colors onto the blocks themselves (dunno if this does anything but it tidies everything up nicely) and made a bool onto the block checking if the block's color had already been set. If so, then don't set it again.
That seemed to work flawlessly and now it stays on 60 fps with size 100 on the terrain (cheer!) However, making larger terrain will lag it, so I recommend (if you're doing this too) making a view distance that makes blocks disappear at a certain distance and bring them back once you get closer.