- Home /
Smooth Voxel terrain. How is it done?
Hello Unity Community!
I am a young student developer and started off with Unity a few months ago. I understand most of the basics and I started following these tutorials for Voxel terrain engines:
http://forum.unity3d.com/threads/198651-Tutorial-Procedural-meshes-and-voxel-terrain-C
http://www.youtube.com/watch?v=_3ZODVA0yKQ
I’m planning on making a smooth, destructible Voxel terrain, like in these games:
I’ve read a few Threads: (After playing Minecraft... etc). I read that one solution would be making a basic Voxel terrain and changing the mesh’s vertices depending on its neighbours. I tried this on a 2D terrain. Here's the code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class SmoothPolygonGeneratorTest : MonoBehaviour {
public List<Vector3> newVertices = new List<Vector3>();
public List<int> newTriangles = new List<int>();
public List<Vector2> newUV = new List<Vector2>();
public List<Vector3> colVertices = new List<Vector3>();
public List<int> colTriangles = new List<int>();
private int colCount;
private Mesh mesh;
private MeshCollider col;
private float tUnit = 0.25f;
private Vector2 tStone = new Vector2 (1, 0);
private Vector2 tGrass = new Vector2 (0, 1);
private Vector2 tRandom = new Vector2 (0, 2);
public byte[,] blocks;
private int squareCount;
public bool update=false;
// Use this for initialization
void Start () {
mesh = GetComponent<MeshFilter> ().mesh;
col = GetComponent<MeshCollider> ();
GenTerrain();
BuildMesh();
UpdateMesh();
}
void Update(){
if(update){
BuildMesh();
UpdateMesh();
update=false;
}
}
int NoiseInt (int x, int y, float scale, float mag, float exp){
return (int) (Mathf.Pow ((Mathf.PerlinNoise(x/scale,y/scale)*mag),(exp) ));
}
void GenTerrain(){
blocks=new byte[96,128];
for(int px=0;px<blocks.GetLength(0);px++){
int stone= NoiseInt(px,0, 80,15,1);
stone+= NoiseInt(px,0, 50,30,1);
stone+= NoiseInt(px,0, 10,10,1);
stone+=75;
int dirt = NoiseInt(px,0, 100f,35,1);
dirt+= NoiseInt(px,100, 50,30,1);
dirt+=75;
for(int py=0;py<blocks.GetLength(1);py++){
if(py<stone){
blocks[px, py]=1;
if(NoiseInt(px,py,12,16,1)>10){ //dirt spots
blocks[px,py]=2;
}
if(NoiseInt(px,py*2,16,14,1)>10){ //Caves
blocks[px,py]=0;
}
} else if(py<dirt) {
blocks[px,py]=2;
}
}
}
}
void BuildMesh(){
for(int px=1;px<blocks.GetLength(0);px++){
for(int py=1;py<blocks.GetLength(1);py++){
if(blocks[px,py]!=0){
if(blocks[px,py]==1){
if(Block(px, py + 1)==0 && Block(px, py-1) == 0) {
if(Block (px + 1, py) != 0 && Block (px - 1, py)== 0) {
SmoothTerrain(px,py,7,tStone,0f);
}
else if (Block (px + 1, py) == 0 && Block (px -1, py) != 0) {
SmoothTerrain(px,py,8,tStone,0f);
}
else if(Block(px - 1, py)==0 || Block(px + 1, py)==0) {
SmoothSquare(px,py,tStone,0f,0f);
}
else if (Block(px - 1, py)!=0 || Block(px + 1, py)!=0) {
SmoothSquare(px,py,tStone,0f,0f);
}
}
else if(Block(px, py + 1 )==0 && Block(px,py -1)!=0) {
if(Block(px + 1, py)!=0 && Block(px- 1, py)==0) {
if (CheckBlock(px + 2,py) != 0 && CheckBlock(px + 1, py +1) == 0){
SmoothTerrain(px,py,1,tStone,0.4f);
}
else {
SmoothTerrain(px,py,1,tStone,0f);
}
}
else if(Block(px - 1, py)!=0 && Block(px + 1, py)==0){
if (CheckBlock(px - 2,py) != 0 && CheckBlock(px - 1, py +1) == 0){
SmoothTerrain(px,py,2,tStone,0.4f);
}
else {
SmoothTerrain(px,py,2,tStone,0f);
}
}
else if(Block(px - 1, py)==0 || Block(px + 1, py)==0) {
SmoothTerrain(px,py,3,tStone, 0f);
}
else if (Block(px - 1, py)!=0 || Block(px + 1, py)!=0) {
if(CheckBlock(px-2,py) ==0 && CheckBlock(px-1, py +1)==0) {
SmoothSquare(px,py,tStone,0.4f,0f);
}
else if(CheckBlock(px+2,py) ==0 && CheckBlock(px+1, py +1)==0) {
SmoothSquare(px,py,tStone,0f,0.4f);
}
else {
SmoothSquare(px,py,tStone,0f,0f);
}
}
}
else if(Block(px, py -1)==0 && Block (px, py +1)!=0) {
if(Block(px + 1, py)!=0 && Block(px- 1, py)==0) {
SmoothTerrain(px,py,4,tStone, 0f);
}
else if(Block(px - 1, py)!=0 && Block(px + 1, py)==0){
SmoothTerrain(px,py,5,tStone, 0f);
}
else if(Block(px - 1, py)==0 || Block(px + 1, py)==0) {
SmoothTerrain(px,py,6,tStone, 0f);
}
else if (Block(px - 1, py)!=0 || Block(px + 1, py)!=0) {
SmoothSquare(px,py,tStone,0f,0f);
}
}
else if(Block (px, py -1) != 0 && Block (px, py + 1) != 0) {
if(Block (px + 1, py) == 0 && Block (px -1, py) == 0){
SmoothSquare(px,py,tStone,0f,0f);
}
else if (Block (px + 1, py) != 0 && Block (px - 1, py) == 0) {
SmoothSquare(px,py,tStone,0f,0f);
}
else if (Block (px + 1, py) == 0 && Block (px - 1, py) != 0) {
SmoothSquare(px,py,tStone,0f,0f);
}
else if(Block (px + 1, py)!= 0 && Block (px- 1, py)!= 0){
GenSquare(px,py,tStone);
}
}
} else if(blocks[px,py]==2){
if(Block(px, py + 1)==0 && Block(px, py-1) == 0) {
if(Block (px + 1, py) != 0 && Block (px - 1, py)== 0) {
SmoothTerrain(px,py,7,tGrass,0f);
}
else if (Block (px + 1, py) == 0 && Block (px -1, py) != 0) {
SmoothTerrain(px,py,8,tGrass,0f);
}
else if(Block(px - 1, py)==0 || Block(px + 1, py)==0) {
SmoothSquare(px,py,tGrass,0f,0f);
}
else if (Block(px - 1, py)!=0 || Block(px + 1, py)!=0) {
SmoothSquare(px,py,tGrass,0f,0f);
}
}
else if(Block(px, py + 1 )==0 && Block(px,py -1)!=0) {
if(Block(px + 1, py)!=0 && Block(px- 1, py)==0) {
if (CheckBlock(px + 2,py) != 0 && CheckBlock(px + 1, py +1) == 0){
SmoothTerrain(px,py,1,tGrass,0.4f);
}
else {
SmoothTerrain(px,py,1,tGrass,0f);
}
}
else if(Block(px - 1, py)!=0 && Block(px + 1, py)==0){
if (CheckBlock(px - 2,py) != 0 && CheckBlock(px - 1, py +1) == 0){
SmoothTerrain(px,py,2,tGrass,0.4f);
}
else {
SmoothTerrain(px,py,2,tGrass,0f);
}
}
else if(Block(px - 1, py)==0 || Block(px + 1, py)==0) {
SmoothTerrain(px,py,3,tGrass, 0f);
}
else if (Block(px - 1, py)!=0 || Block(px + 1, py)!=0) {
if(CheckBlock(px-2,py) ==0 && CheckBlock(px-1, py +1)==0) {
SmoothSquare(px,py,tGrass,0.4f,0f);
}
else if(CheckBlock(px+2,py) ==0 && CheckBlock(px+1, py +1)==0) {
SmoothSquare(px,py,tGrass,0f,0.4f);
}
else {
SmoothSquare(px,py,tGrass,0f,0f);
}
}
}
else if(Block(px, py -1)==0 && Block (px, py +1)!=0) {
if(Block(px + 1, py)!=0 && Block(px- 1, py)==0) {
SmoothTerrain(px,py,4,tGrass, 0f);
}
else if(Block(px - 1, py)!=0 && Block(px + 1, py)==0){
SmoothTerrain(px,py,5,tGrass, 0f);
}
else if(Block(px - 1, py)==0 || Block(px + 1, py)==0) {
SmoothTerrain(px,py,6,tGrass, 0f);
}
else if (Block(px - 1, py)!=0 || Block(px + 1, py)!=0) {
SmoothSquare(px,py,tGrass,0f,0f);
}
}
else if(Block (px, py -1) != 0 && Block (px, py + 1) != 0) {
if(Block (px + 1, py) == 0 && Block (px -1, py) == 0){
SmoothSquare(px,py,tGrass,0f,0f);
}
else if (Block (px + 1, py) != 0 && Block (px - 1, py) == 0) {
SmoothSquare(px,py,tGrass,0f,0f);
}
else if (Block (px + 1, py) == 0 && Block (px - 1, py) != 0) {
SmoothSquare(px,py,tGrass,0f,0f);
}
else if(Block (px + 1, py)!= 0 && Block (px- 1, py)!= 0){
GenSquare(px,py,tGrass);
}
}
}
}
}
}
}
byte Block (int x, int y){
if(x==-1 || x==blocks.GetLength(0) || y==-1 || y==blocks.GetLength(1)){
return (byte)1;
}
return blocks[x,y];
}
byte CheckBlock (int x, int y) {
if( x == -1 || x == -2 || x ==blocks.GetLength(0) + 1 || x ==blocks.GetLength(0) || y == -1 || y == -2 || y == blocks.GetLength(1) + 1 || y == blocks.GetLength(1) ) {
return (byte) 1;
}
return blocks[x,y];
}
void GenSquare(int x, int y, Vector2 texture){
newVertices.Add( new Vector3 (x , y , 0 ));
newVertices.Add( new Vector3 (x + 1 , y , 0 ));
newVertices.Add( new Vector3 (x + 1 , y-1 , 0 ));
newVertices.Add( new Vector3 (x , y-1 , 0 ));
newTriangles.Add(squareCount*4);
newTriangles.Add((squareCount*4)+1);
newTriangles.Add((squareCount*4)+3);
newTriangles.Add((squareCount*4)+1);
newTriangles.Add((squareCount*4)+2);
newTriangles.Add((squareCount*4)+3);
newUV.Add(new Vector2 (tUnit * texture.x, tUnit * texture.y + tUnit));
newUV.Add(new Vector2 (tUnit * texture.x + tUnit, tUnit * texture.y + tUnit));
newUV.Add(new Vector2 (tUnit * texture.x + tUnit, tUnit * texture.y));
newUV.Add(new Vector2 (tUnit * texture.x, tUnit * texture.y));
squareCount++;
}
void UpdateMesh () {
mesh.Clear ();
mesh.vertices = newVertices.ToArray();
mesh.triangles = newTriangles.ToArray();
mesh.uv = newUV.ToArray();
mesh.Optimize ();
mesh.RecalculateNormals ();
newVertices.Clear();
newTriangles.Clear();
newUV.Clear();
squareCount=0;
Mesh newMesh = new Mesh();
newMesh.vertices = colVertices.ToArray();
newMesh.triangles = colTriangles.ToArray();
col.sharedMesh= newMesh;
colVertices.Clear();
colTriangles.Clear();
colCount=0;
}
void SmoothTerrain(int x, int y, int count, Vector2 texture, float rate) {
if(count == 1) {
newVertices.Add( new Vector3 (x , y , 0 ));
newVertices.Add( new Vector3 (x + 1 , y- rate , 0 ));
newVertices.Add( new Vector3 (x + 1 , y-1 , 0 ));
newVertices.Add( new Vector3 (x , y-1 , 0 ));
newTriangles.Add((squareCount*4)+1);
newTriangles.Add((squareCount*4)+2);
newTriangles.Add((squareCount*4)+3);
newUV.Add(new Vector2 (tUnit * texture.x, tUnit * texture.y + tUnit));
newUV.Add(new Vector2 (tUnit * texture.x + tUnit, tUnit * texture.y + tUnit));
newUV.Add(new Vector2 (tUnit * texture.x + tUnit, tUnit * texture.y));
newUV.Add(new Vector2 (tUnit * texture.x, tUnit * texture.y));
colVertices.Add( new Vector3 (x , y-1 , 1));
colVertices.Add( new Vector3 (x + 1 , y- rate , 1));
colVertices.Add( new Vector3 (x + 1 , y- rate , 0 ));
colVertices.Add( new Vector3 (x , y-1 , 0 ));
ColliderTriangles();
colCount++;
squareCount++;
}
else if(count == 2) {
newVertices.Add( new Vector3 (x , y , 0 ));
newVertices.Add( new Vector3 (x , y- rate , 0 ));
newVertices.Add( new Vector3 (x + 1 , y-1 , 0 ));
newVertices.Add( new Vector3 (x , y-1 , 0 ));
newTriangles.Add((squareCount*4)+3);
newTriangles.Add((squareCount*4)+1);
newTriangles.Add((squareCount*4)+2);
newUV.Add(new Vector2 (tUnit * texture.x, tUnit * texture.y + tUnit));
newUV.Add(new Vector2 (tUnit * texture.x + tUnit, tUnit * texture.y + tUnit));
newUV.Add(new Vector2 (tUnit * texture.x + tUnit, tUnit * texture.y));
newUV.Add(new Vector2 (tUnit * texture.x, tUnit * texture.y));
colVertices.Add( new Vector3 (x , y- rate , 0));
colVertices.Add( new Vector3 (x , y- rate , 1));
colVertices.Add( new Vector3 (x + 1 , y-1 , 1 ));
colVertices.Add( new Vector3 (x +1 , y-1 , 0 ));
ColliderTriangles();
colCount++;
squareCount++;
}
else if (count == 3) {
newVertices.Add( new Vector3 (x , y , 0 ));
newVertices.Add( new Vector3 (x+1 , y-1 , 0 ));
newVertices.Add( new Vector3 (x + 0.5f , y-0.5f , 0 ));
newVertices.Add( new Vector3 (x , y-1 , 0 ));
newTriangles.Add((squareCount*4)+3);
newTriangles.Add((squareCount*4)+2);
newTriangles.Add((squareCount*4)+1);
newUV.Add(new Vector2 (tUnit * texture.x, tUnit * texture.y + tUnit));
newUV.Add(new Vector2 (tUnit * texture.x + tUnit, tUnit * texture.y + tUnit));
newUV.Add(new Vector2 (tUnit * texture.x + tUnit, tUnit * texture.y));
newUV.Add(new Vector2 (tUnit * texture.x, tUnit * texture.y));
colVertices.Add( new Vector3 (x , y-1 , 0));
colVertices.Add( new Vector3 (x , y-1 , 1));
colVertices.Add( new Vector3 (x + 0.5f , y-0.5f , 1 ));
colVertices.Add( new Vector3 (x+0.5f , y-0.5f , 0 ));
ColliderTriangles();
colCount++;
colVertices.Add( new Vector3 (x + 0.5f , y-0.5f , 0 ));
colVertices.Add( new Vector3 (x+0.5f , y-0.5f , 1 ));
colVertices.Add( new Vector3 (x+1 , y-1 , 1 ));
colVertices.Add( new Vector3 (x+1 , y-1 , 0 ));
ColliderTriangles();
colCount++;
squareCount++;
}
else if(count == 4) {
newVertices.Add( new Vector3 (x , y , 0 ));
newVertices.Add( new Vector3 (x + 1 , y , 0 ));
newVertices.Add( new Vector3 (x + 1 , y-(1 - rate) , 0 ));
newVertices.Add( new Vector3 (x , y-1 , 0 ));
newTriangles.Add((squareCount*4)+0);
newTriangles.Add((squareCount*4)+1);
newTriangles.Add((squareCount*4)+2);
newUV.Add(new Vector2 (tUnit * texture.x, tUnit * texture.y + tUnit));
newUV.Add(new Vector2 (tUnit * texture.x + tUnit, tUnit * texture.y + tUnit));
newUV.Add(new Vector2 (tUnit * texture.x + tUnit, tUnit * texture.y));
newUV.Add(new Vector2 (tUnit * texture.x, tUnit * texture.y));
colVertices.Add( new Vector3 (x , y , 0));
colVertices.Add( new Vector3 (x , y , 1));
colVertices.Add( new Vector3 (x + 1 , y-(1 - rate) , 1 ));
colVertices.Add( new Vector3 (x +1 , y-(1-rate) , 0 ));
ColliderTriangles();
colCount++;
squareCount++;
}
else if(count == 5) {
newVertices.Add( new Vector3 (x , y , 0 ));
newVertices.Add( new Vector3 (x + 1 , y , 0 ));
newVertices.Add( new Vector3 (x + 1 , y-1 , 0 ));
newVertices.Add( new Vector3 (x , y-(1-rate) , 0 ));
newTriangles.Add((squareCount*4)+0);
newTriangles.Add((squareCount*4)+1);
newTriangles.Add((squareCount*4)+3);
newUV.Add(new Vector2 (tUnit * texture.x, tUnit * texture.y + tUnit));
newUV.Add(new Vector2 (tUnit * texture.x + tUnit, tUnit * texture.y + tUnit));
newUV.Add(new Vector2 (tUnit * texture.x + tUnit, tUnit * texture.y));
newUV.Add(new Vector2 (tUnit * texture.x, tUnit * texture.y));
colVertices.Add( new Vector3 (x +1 , y , 0));
colVertices.Add( new Vector3 (x +1 , y , 1));
colVertices.Add( new Vector3 (x , y-(1 - rate) , 1 ));
colVertices.Add( new Vector3 (x , y-(1-rate) , 0 ));
ColliderTriangles();
colCount++;
squareCount++;
}
else if (count == 6) {
newVertices.Add( new Vector3 (x , y , 0 ));
newVertices.Add( new Vector3 (x+1 , y , 0 ));
newVertices.Add( new Vector3 (x + 0.5f , y-0.5f , 0 ));
newVertices.Add( new Vector3 (x , y-1 , 0 ));
newTriangles.Add((squareCount*4)+0);
newTriangles.Add((squareCount*4)+1);
newTriangles.Add((squareCount*4)+2);
newUV.Add(new Vector2 (tUnit * texture.x, tUnit * texture.y + tUnit));
newUV.Add(new Vector2 (tUnit * texture.x + tUnit, tUnit * texture.y + tUnit));
newUV.Add(new Vector2 (tUnit * texture.x + tUnit, tUnit * texture.y));
newUV.Add(new Vector2 (tUnit * texture.x, tUnit * texture.y));
colVertices.Add( new Vector3 (x , y , 0));
colVertices.Add( new Vector3 (x , y , 1));
colVertices.Add( new Vector3 (x + 0.5f , y-0.5f , 1 ));
colVertices.Add( new Vector3 (x+0.5f , y-0.5f , 0 ));
ColliderTriangles();
colCount++;
colVertices.Add( new Vector3 (x + 0.5f , y-0.5f , 0 ));
colVertices.Add( new Vector3 (x+0.5f , y-0.5f , 1 ));
colVertices.Add( new Vector3 (x+1 , y , 1 ));
colVertices.Add( new Vector3 (x+1 , y , 0 ));
ColliderTriangles();
colCount++;
squareCount++;
}
else if (count == 7) {
newVertices.Add( new Vector3 (x , y , 0 ));
newVertices.Add( new Vector3 (x+1 , y , 0 ));
newVertices.Add( new Vector3 (x + 0.5f , y-0.5f , 0 ));
newVertices.Add( new Vector3 (x+1 , y-1 , 0 ));
newTriangles.Add((squareCount*4)+1);
newTriangles.Add((squareCount*4)+3);
newTriangles.Add((squareCount*4)+2);
newUV.Add(new Vector2 (tUnit * texture.x, tUnit * texture.y + tUnit));
newUV.Add(new Vector2 (tUnit * texture.x + tUnit, tUnit * texture.y + tUnit));
newUV.Add(new Vector2 (tUnit * texture.x + tUnit, tUnit * texture.y));
newUV.Add(new Vector2 (tUnit * texture.x, tUnit * texture.y));
colVertices.Add( new Vector3 (x + 1 , y-1 , 0));
colVertices.Add( new Vector3 (x + 1 , y-1 , 1));
colVertices.Add( new Vector3 (x + 0.5f , y-0.5f , 1 ));
colVertices.Add( new Vector3 (x+0.5f , y-0.5f , 0 ));
ColliderTriangles();
colCount++;
colVertices.Add( new Vector3 (x + 0.5f , y-0.5f , 0 ));
colVertices.Add( new Vector3 (x+0.5f , y-0.5f , 1 ));
colVertices.Add( new Vector3 (x+1 , y , 1 ));
colVertices.Add( new Vector3 (x+1 , y , 0 ));
ColliderTriangles();
colCount++;
squareCount++;
}
else if (count == 8) {
newVertices.Add( new Vector3 (x , y , 0 ));
newVertices.Add( new Vector3 (x , y , 0 ));
newVertices.Add( new Vector3 (x + 0.5f , y-0.5f , 0 ));
newVertices.Add( new Vector3 (x , y-1 , 0 ));
newTriangles.Add((squareCount*4)+1);
newTriangles.Add((squareCount*4)+2);
newTriangles.Add((squareCount*4)+3);
newUV.Add(new Vector2 (tUnit * texture.x, tUnit * texture.y + tUnit));
newUV.Add(new Vector2 (tUnit * texture.x + tUnit, tUnit * texture.y + tUnit));
newUV.Add(new Vector2 (tUnit * texture.x + tUnit, tUnit * texture.y));
newUV.Add(new Vector2 (tUnit * texture.x, tUnit * texture.y));
colVertices.Add( new Vector3 (x , y-1 , 0));
colVertices.Add( new Vector3 (x , y-1 , 1));
colVertices.Add( new Vector3 (x + 0.5f , y-0.5f , 1 ));
colVertices.Add( new Vector3 (x+0.5f , y-0.5f , 0 ));
ColliderTriangles();
colCount++;
colVertices.Add( new Vector3 (x + 0.5f , y-0.5f , 0 ));
colVertices.Add( new Vector3 (x+0.5f , y-0.5f , 1 ));
colVertices.Add( new Vector3 (x , y , 1 ));
colVertices.Add( new Vector3 (x , y , 0 ));
ColliderTriangles();
colCount++;
squareCount++;
}
}
void SmoothSquare(int x, int y, Vector2 texture, float rate, float brate) {
newVertices.Add( new Vector3 (x , y-rate , 0 ));
newVertices.Add( new Vector3 (x + 1 , y -brate, 0 ));
newVertices.Add( new Vector3 (x + 1 , y-1 , 0 ));
newVertices.Add( new Vector3 (x , y-1 , 0 ));
newTriangles.Add(squareCount*4);
newTriangles.Add((squareCount*4)+1);
newTriangles.Add((squareCount*4)+3);
newTriangles.Add((squareCount*4)+1);
newTriangles.Add((squareCount*4)+2);
newTriangles.Add((squareCount*4)+3);
newUV.Add(new Vector2 (tUnit * texture.x, tUnit * texture.y + tUnit));
newUV.Add(new Vector2 (tUnit * texture.x + tUnit, tUnit * texture.y + tUnit));
newUV.Add(new Vector2 (tUnit * texture.x + tUnit, tUnit * texture.y));
newUV.Add(new Vector2 (tUnit * texture.x, tUnit * texture.y));
if(Block(x,y+1)==0){
colVertices.Add( new Vector3 (x , y - rate , 1));
colVertices.Add( new Vector3 (x + 1 , y - brate , 1));
colVertices.Add( new Vector3 (x + 1 , y - brate, 0 ));
colVertices.Add( new Vector3 (x , y - rate , 0 ));
ColliderTriangles();
colCount++;
}
//bot
if(Block(x,y-1)==0){
colVertices.Add( new Vector3 (x , y -1 , 0));
colVertices.Add( new Vector3 (x + 1 , y -1 , 0));
colVertices.Add( new Vector3 (x + 1 , y -1 , 1 ));
colVertices.Add( new Vector3 (x , y -1 , 1 ));
ColliderTriangles();
colCount++;
}
//left
if(Block(x-1,y)==0){
colVertices.Add( new Vector3 (x , y -1 , 1));
colVertices.Add( new Vector3 (x , y , 1));
colVertices.Add( new Vector3 (x , y , 0 ));
colVertices.Add( new Vector3 (x , y -1 , 0 ));
ColliderTriangles();
colCount++;
}
//right
if(Block(x+1,y)==0){
colVertices.Add( new Vector3 (x +1 , y , 1));
colVertices.Add( new Vector3 (x +1 , y , 0));
colVertices.Add( new Vector3 (x +1 , y -1 , 0 ));
colVertices.Add( new Vector3 (x +1 , y-1 , 1 ));
ColliderTriangles();
colCount++;
}
squareCount++;
}
void ColliderTriangles(){
colTriangles.Add(colCount*4);
colTriangles.Add((colCount*4)+1);
colTriangles.Add((colCount*4)+3);
colTriangles.Add((colCount*4)+1);
colTriangles.Add((colCount*4)+2);
colTriangles.Add((colCount*4)+3);
}
}
before changes on script
after
Is this the right way or would the performance be too slow? Is an obvious better way? (By maybe setting meshes vertices by Perlin Noise, if it´s even possible). Because I have otherwise no idea, what to do. I would really appreciate your support! :)
You can code a chunks system for the terrain. It doesn't boost the performance but it hide the problem. You can generate the chunks one by one in several frames. And every time you change anything on terrain, you just have to update one chunk. It's also a must if you want to make it open and infinitely large as $$anonymous$$inecraft.
A chunk based system will most definitely increase performance, but multi-threading would need to be coded up first. It helps with performance, because each thread can handle it's own chunk of data simultaneously.
I have a free tool to handle dividing works between frames and threads for free on the Asset Store. https://www.assetstore.unity3d.com/#/content/12435
The intent is to keep the tool very simple even if it's quite advanced under the hood. :) Hope this helps when you start threading. Just remember DO NOT USE THREADPOOLS! Unity uses threadpools for all kind of things and things get relay messy.
Answer by Spiderbean · May 07, 2014 at 05:23 PM
I have made a lot of progress and implemented a 3D marching cubed algorithm. Of course there are still little things not working correctly yet. I would like you guys to maybe have a look. ;-) Marching Cubes terrain deformation
Answer by JohanHoltby · Feb 06, 2014 at 11:39 AM
Your code base will expand a lot. I would strongly suggest reading a book like "Clean Code: A Handbook of Agile Software Craftsmanship". Other vise you will end up with problems increase exponentially with your code base. This is not an exact answer but it will help you! Good luck!
Thanks for your answer! You might be right and I am thankful for taking your time. But I first wanted to know if it is at least going in the right direction.
I completely agree with Norritt42. This should not all be in a single class. Also, once you get it cleaned up, you'll likely want to take a chunk based approach, and push each of those chunks off into their own thread. Voxel engine need to be finely tuned and optimized. This is due to the sheer amount of iteration that must happen. Because you have so many (hundreds of thousands if not more) data points that all need to be processed, it is one of the few times in software development where micro-optimizations aren't actually frowned upon.
The first thing to do, is to get it to work, then clean it up, then once it's clean, working, and bug-free, do a round of optimizations.
I agree with justin35f in part. Try to divide every thing in to small modules and for each module do the "get it to work, then clean it up" the optimization should come at the very last step since the optimizations is a trade of between good looking code and fast code. When you are debugging your complete system you want good looking code. One more thing for each module which works good for me is UnitTesting (http://en.wikipedia.org/wiki/Unit_testing).
The code base i did learn how to this from was http://www.youtube.com/watch?v=cgW$$anonymous$$75QTr2o see source in description of his videos.