You forgot to add X-
face
using UnityEngine;
public class TerrainChunk : MonoBehaviour
{
[SerializeField] Material _material;
void Start ()
{
Vector3[] vertices =
{
new Vector3(0,0,0),// 0
new Vector3(1,0,0),// 1
new Vector3(1,1,0),// 2
new Vector3(0,1,0),// 3
new Vector3(0,1,1),// 4
new Vector3(1,1,1),// 5
new Vector3(1,0,1),// 6
new Vector3(0,0,1),// 7
};
/// 5--------2
/// /| /|
/// / | / |
/// 4--------3 |
/// | | | |
/// | 6---- | -1 Y
/// | / | / | X
/// |/ |/ |/
/// 7--------0 Z---+
int[] triangles =
{
1,2,5, 1,5,6,// X+ face
7,4,3, 7,3,0,// X- face
2,3,4, 2,4,5,// Y+ face
0,1,6, 0,6,7,// Y- face
6,5,4, 6,4,7,// Z+ face
0,3,2, 0,2,1,// Z- face
};
Mesh mesh = new Mesh();
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.RecalculateNormals();
GameObject tempPrefab = new GameObject("cube");
MeshFilter mf = tempPrefab.AddComponent<MeshFilter>();
mf.sharedMesh = mesh;
MeshRenderer mr = tempPrefab.AddComponent<MeshRenderer>();
mr.sharedMaterial = _material;
for( int x = 0 ; x<16 ; x++ )
for( int z = 0 ; z<16 ; z++ )
{
Instantiate(tempPrefab , new Vector3(x , 0 , z) , Quaternion.identity);
}
Destroy( tempPrefab );
}
}
Your next step is to to this - merge them into a single mesh like this:
using System.Collections.Generic;
using UnityEngine;
public class TerrainChunk : MonoBehaviour
{
[SerializeField] MeshFilter _meshFilter;
[SerializeField] Vector3 _cubeSize = Vector3.one;
void Start ()
{
/// C--------D
/// /| /|
/// / | / |
/// B--------A |
/// | | | |
/// | G---- | -H Y
/// | / | / | X
/// |/ |/ |/
/// F--------E Z---+
Vector3 A = Vector3.Scale( new Vector3(0,1,0) , _cubeSize );// Vector3.Scale is Vector3*Vector3 multiplication
Vector3 B = Vector3.Scale( new Vector3(0,1,1) , _cubeSize );
Vector3 C = Vector3.Scale( new Vector3(1,1,1) , _cubeSize );
Vector3 D = Vector3.Scale( new Vector3(1,1,0) , _cubeSize );
Vector3 E = Vector3.Scale( new Vector3(0,0,0) , _cubeSize );
Vector3 F = Vector3.Scale( new Vector3(0,0,1) , _cubeSize );
Vector3 G = Vector3.Scale( new Vector3(1,0,1) , _cubeSize );
Vector3 H = Vector3.Scale( new Vector3(1,0,0) , _cubeSize );
Vector3[] rightVertices = { H,D,C,G };// x+ face
Vector3[] leftVertices = { F,B,A,E };// x- face
Vector3[] upVertices = { A,B,C,D };// y+ face
Vector3[] downVertices = { F,E,H,G };// y- face
Vector3[] forwardVertices = { G,C,B,F };// z+ face
Vector3[] backVertices = { E,A,D,H };// z- face
Vector3[] rightNormals = { Vector3.right, Vector3.right, Vector3.right, Vector3.right };// x+ face
Vector3[] leftNormals = { Vector3.left, Vector3.left, Vector3.left, Vector3.left };// x- face
Vector3[] upNormals = { Vector3.up, Vector3.up, Vector3.up, Vector3.up };// y+ face
Vector3[] downNormals = { Vector3.down, Vector3.down, Vector3.down, Vector3.down };// y- face
Vector3[] forwardNormals = { Vector3.forward, Vector3.forward, Vector3.forward, Vector3.forward };// z+ face
Vector3[] backNormals = { Vector3.back, Vector3.back, Vector3.back, Vector3.back };// z- face
Vector2[] rightUV = { new Vector2(0,0),new Vector2(0,0.5f),new Vector2(0.5f,0.5f),new Vector2(0.5f,0), };// x+
Vector2[] leftUV = { new Vector2(0,0),new Vector2(0,0.5f),new Vector2(0.5f,0.5f),new Vector2(0.5f,0), };// x-
Vector2[] upUV = { new Vector2(0,0.5f),new Vector2(0,1),new Vector2(0.5f,1),new Vector2(0.5f,0.5f), };// y+
Vector2[] downUV = { new Vector2(0.5f,0.5f),new Vector2(0.5f,1),new Vector2(1,1),new Vector2(1,0.5f), };// y-
Vector2[] forwardUV = { new Vector2(0.5f,0),new Vector2(0.5f,0.5f),new Vector2(1,0.5f),new Vector2(1,0), };// z+
Vector2[] backUV = { new Vector2(0.5f,0),new Vector2(0.5f,0.5f),new Vector2(1,0.5f),new Vector2(1,0), };// z-
int[] faceIndices = { 0,1,2, 0,2,3 };// assumes identical order of vertices
List<Vector3> vertices = new();
List<Vector3> normals = new();
List<Vector2> uvs = new();
List<int> indices = new();
int index = 0;// you need to store
for( int y=0 ; y<1 ; y++ )
for( int x=0 ; x<16 ; x++ )
for( int z=0 ; z<16 ; z++ )
{
Vector3 cellPosition = Vector3.Scale( new Vector3(x,y,z) , _cubeSize );// Vector3.Scale is Vector3*Vector3 multiplication
// x+ / right face
if( true )// TODO: false when there is a cube in this direction
{
foreach( Vector3 vertex in rightVertices )
vertices.Add( cellPosition + vertex );
normals.AddRange( rightNormals );
uvs.AddRange( rightUV );
foreach( int i in faceIndices )
indices.Add( index+i );
index += rightVertices.Length;
}
// x- / left face
if( true )// TODO: false when there is a cube in this direction
{
foreach( Vector3 vertex in leftVertices )
vertices.Add( cellPosition + vertex );
normals.AddRange( leftNormals );
uvs.AddRange( leftUV );
foreach( int i in faceIndices )
indices.Add( index+i );
index += leftVertices.Length;
}
// y+ / up face
if( true )// TODO: false when there is a cube in this direction
{
foreach( Vector3 vertex in upVertices )
vertices.Add( cellPosition + vertex );
normals.AddRange( upNormals );
uvs.AddRange( upUV );
foreach( int i in faceIndices )
indices.Add( index+i );
index += upVertices.Length;
}
// y- / down face
if( true )// TODO: false when there is a cube in this direction
{
foreach( Vector3 vertex in downVertices )
vertices.Add( cellPosition + vertex );
normals.AddRange( downNormals );
uvs.AddRange( downUV );
foreach( int i in faceIndices )
indices.Add( index+i );
index += downVertices.Length;
}
// z+ / forward face
if( true )// TODO: false when there is a cube in this direction
{
foreach( Vector3 vertex in forwardVertices )
vertices.Add( cellPosition + vertex );
normals.AddRange( forwardNormals );
uvs.AddRange( forwardUV );
foreach( int i in faceIndices )
indices.Add( index+i );
index += forwardVertices.Length;
}
// z- / back face
if( true )// TODO: false when there is a cube in this direction
{
foreach( Vector3 vertex in backVertices )
vertices.Add( cellPosition + vertex );
normals.AddRange( backNormals );
uvs.AddRange( backUV );
foreach( int i in faceIndices )
indices.Add( index+i );
index += backVertices.Length;
}
}
Mesh mesh = new Mesh();
mesh.name = "procedural mesh";
mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;// higher mesh complexity limit
mesh.SetVertices( vertices );
mesh.SetNormals( normals );
mesh.SetUVs( 0 , uvs );
mesh.SetTriangles( indices , 0 );
_meshFilter.sharedMesh = mesh;
}
}