Trying to generate a sphere made of cubes like so:
This was easy, but any sphere of significant sizes has obvious performance issues if each cube is a separate gameobject, especially if the sphere is solid. After some digging, the answer appears to be to create a single mesh from only the exposed edges. Okay, makes sense. Found several videos, this one was the best I could find: link
I was able to customize the script for my needs, but I keep getting what appears to be a 2x2x2 cube regardless of the diameter input. I should be getting a hollow sphere made of a single mesh.
I suspect the issue is that I am not attaching the script to the correct type of gameobject, am missing a needed component on the gameobject, or because I skipped the UV portion.
Can anyone offer some advice?
Code:
public class PlanetGeneration : MonoBehaviour
{
private int planetDia = 30;
private int planetRadius;
//array of bools to keep track if each space is solid(true) or void(false)
private bool[,,] currentPlanet;
void Start()
{
currentPlanet = new bool[planetDia, planetDia, planetDia];
planetRadius = planetDia / 2 + 1;
GeneratePlanet();
GenerateMesh();
}
//define each block as void or solid
public void GeneratePlanet()
{
Vector3 planetCenter = new(planetRadius, planetRadius, planetRadius);
Vector3 currentPoint;
for (int x = 0; x < planetDia; x++)
{
for (int y = 0; y < planetDia; y++)
{
for (int z = 0; z < planetDia; z++)
{
//set the current position
currentPoint = new Vector3(x, y, z);
//check if this point is within the desired planet size
if (Vector3.Distance(planetCenter, currentPoint) <= planetRadius)
{
//make it a solid block
currentPlanet[x, y, z] = true;
}
//make it void
else currentPlanet[x, y, z] = false;
}
}
}
}
//generate mesh
public void GenerateMesh()
{
List<Vector3> Vertices = new List<Vector3>();
List<int> Triangles = new List<int>();
for (int x = 0; x < planetDia; x++)
{
for (int y = 0; y < planetDia; y++)
{
for (int z = 0; z < planetDia; z++)
{
//the 8 corners of a cube
Vector3[] VertexPos = new Vector3[8]
{
new Vector3(-1, 1, -1), new Vector3(-1, 1, 1),
new Vector3(1, 1, 1), new Vector3(1, 1, -1),
new Vector3(-1, -1, -1), new Vector3(-1, -1, 1),
new Vector3(1, -1, 1), new Vector3(1, -1, -1),
};
//first 4 digits are the vertices of the face, and the last 3 are the relative coords of the next block in that direction
int[,] Faces = new int[6, 7]{
{0, 1, 2, 3, 0, 1, 0}, //top
{7, 6, 5, 4, 0, -1, 0}, //bottom
{2, 1, 5, 6, 0, 0, 1}, //right
{0, 3, 7, 4, 0, 0, -1}, //left
{3, 2, 6, 7, 1, 0, 0}, //front
{1, 0, 4, 5, -1, 0, 0} //back
};
//if this block is solid
if (currentPlanet[x, y, z] == true)
{
//for each face of the block
for (int i = 0; i < 6; i++)
{
//check if it is on the edge of the overall array
//This part is dumb and needs to be removed. Keeping for now to prevent the array out of bounds error.
if(x + Faces[i, 4] == -1 || y + Faces[i, 5] == -1 || z + Faces[i, 6] == -1 ||
x + Faces[i, 4] == planetDia || y + Faces[i, 5] == planetDia || z + Faces[i, 6] == planetDia)
{
//do nothing
}
//check if the block next to it is void
else if(currentPlanet[x + Faces[i, 4], y + Faces[i, 5], z + Faces[i, 6]] == false)
{
AddQuad(Faces[i, 0], Faces[i, 1], Faces[i, 2], Faces[i, 3], Vertices.Count);
}
}
}
void AddQuad(int ai, int bi, int ci, int di, int i)
{
Vector3 a = VertexPos[ai];
Vector3 b = VertexPos[bi];
Vector3 c = VertexPos[ci];
Vector3 d = VertexPos[di];
Vertices.AddRange(new List<Vector3>() { a, b, c, d });
Triangles.AddRange(new List<int>() { i, i + 1, i + 2, i, i + 2, i + 3 });
}
}
}
}
this.gameObject.GetComponent<MeshFilter>().mesh = new Mesh()
{
vertices = Vertices.ToArray(),
triangles = Triangles.ToArray(),
};
}
}