[Optimization]how to make 1.5k cubes feel like 20?

hi, I am currently trying to make a building game. But unity lags with 1.5k cubes, even with 10 fps loss, I am worried that if someone makes 10k bricks, they will have 1-5FPS.

My question is the title, how do I make gameobject Cubes feel, and lag like nothing?

Ahh I found a partially finished voxel system of my own I made a little while ago, The main things left to do would be setting up texture UV’s on the created meshes and coding an UpdateMesh function so that you have to update as few meshes as possible due to a change in a single block. I’ve tested this upto 300x200x300 blocks (18 million) without runtime framerate loss, however the level does take quite a while to load (this might be quite a lot to do with the engine making a debug call for the meshes not having UV’s which should eventually not happen) though I’d hope 18million cubes would suffice for most situations.

So my classes used, first is for singular voxel blocks to store their information, and second is the class for storing a £D list of these blocks and finally I have attached a test script that you can use to test the other scripts:

Voxel Class

enum VoxelMaterial{Air, Stone}

public class Voxel{
	public var position : Vector3;
	public var size : Vector3;
	public var material : VoxelMaterial;
	public var meshNumber : int;
	public var visible : boolean = true;
	
	public function Voxel(pos : Vector3, s : Vector3, mat : VoxelMaterial, vis : boolean){
		position = pos;
		size = s;
		material = mat;
		visible = vis;
	}
	
	public function Voxel(mshNo : int){
		meshNumber = mshNo;
	}
	
	public function Voxel(){
		position = Vector3(0, 0, 0);
		size = Vector3(1, 1, 1);
		material = VoxelMaterial.Air;
	}
}

Voxel List Class

public class VoxelArray{
	var origin : Vector3 = Vector3.zero;
	var List : Voxel[,,];
	var width : int;
	var height : int;
	var depth : int;
	var defaultSize : Vector3 = Vector3(1, 1, 1);
	var defaultMaterial : VoxelMaterial = VoxelMaterial.Air;
	
	public static function VectorsToList(arr) : Vector3[]{
		var list : Vector3[] = new Vector3[arr.length];
		for(var i = 0; i < arr.length; i++){
			list _= arr*;*_

* }*
* return list;*
* }*
* public static function IntsToList(arr) : int[]{*
* var list : int[] = new int[arr.length];*
* for(var i = 0; i < arr.length; i++){*
list = arr*;*
* }*
* return list;*
* }*
* public static function CreateMesh(vList : VoxelArray){*
* var origin : Vector3 = vList.origin;*
* var List : Voxel[,] = vList.List;*
* var width : int = vList.width;*
* var height : int = vList.height;*
* var depth : int = vList.depth;*
* var size : Vector3 = vList.defaultSize;*

* var meshes = new Array();*

* for(var xBreak : int = 0; xBreak < width; xBreak += 13){*
* for(var yBreak : int = 0; yBreak < height; yBreak += 13){*
* for(var zBreak : int = 0; zBreak < depth; zBreak += 13){*
* var verts = new Array();*
* var tris = new Array();*
* var normals = new Array();*

* for (var x : int = xBreak; x < Mathf.Min(xBreak+13, width); x++){*
* for (var y : int = yBreak; y < Mathf.Min(yBreak+13, height); y++){*
* for(var z : int = zBreak; z < Mathf.Min(zBreak+13, depth); z++){*
* List[x, y, z].meshNumber = meshes.length;*
* if(List[x, y, z].visible){*
* var material = List[x, y, z].material;*
* var position = List[x, y, z].position;*
* var vert1 : Vector3;*
* var vert2 : Vector3;*
* var vert3 : Vector3;*
* var vert4 : Vector3;*
* //X-axis faces*
* if(x == width-1 || !List[Mathf.Min(x+1, width-1), y, z].visible){*
_ vert1 = position+(0.5size);
vert2 = vert1-Vector3(0, size.y, 0);
vert3 = vert2-Vector3(0, 0, size.z);
vert4 = vert3+Vector3(0, size.y, 0);
verts.Add(vert1);
verts.Add(vert2);
verts.Add(vert3);
verts.Add(vert4);
tris.Add(verts.length - 4);
tris.Add(verts.length - 3);
tris.Add(verts.length - 2);
tris.Add(verts.length - 4);
tris.Add(verts.length - 2);
tris.Add(verts.length - 1);
normals.Add(Vector3.right);
normals.Add(Vector3.right);
normals.Add(Vector3.right);
normals.Add(Vector3.right);
}
if(x == 0 || !List[Mathf.Max(x-1, 0), y, z].visible){
vert1 = position-(0.5size);

* vert2 = vert1+Vector3(0, size.y, 0);
vert3 = vert2+Vector3(0, 0, size.z);
vert4 = vert3-Vector3(0, size.y, 0);
verts.Add(vert1);
verts.Add(vert2);
verts.Add(vert3);
verts.Add(vert4);
tris.Add(verts.length - 4);
tris.Add(verts.length - 2);
tris.Add(verts.length - 3);
tris.Add(verts.length - 4);
tris.Add(verts.length - 1);
tris.Add(verts.length - 2);
normals.Add(-Vector3.right);
normals.Add(-Vector3.right);
normals.Add(-Vector3.right);
normals.Add(-Vector3.right);
}
//Z-axis faces*

* if(z == depth-1 || !List[x, y, Mathf.Min(z+1, depth-1)].visible){
vert1 = position+(0.5size);

* vert2 = vert1-Vector3(0, size.y, 0);
vert3 = vert2-Vector3(size.x, 0, 0);
vert4 = vert3+Vector3(0, size.y, 0);
verts.Add(vert1);
verts.Add(vert2);
verts.Add(vert3);
verts.Add(vert4);
tris.Add(verts.length - 4);
tris.Add(verts.length - 2);
tris.Add(verts.length - 3);
tris.Add(verts.length - 4);
tris.Add(verts.length - 1);
tris.Add(verts.length - 2);
normals.Add(Vector3.forward);
normals.Add(Vector3.forward);
normals.Add(Vector3.forward);
normals.Add(Vector3.forward);
}
if(z == 0 || !List[x, y, Mathf.Max(z-1, 0)].visible){
vert1 = position-(0.5size);

* vert2 = vert1+Vector3(0, size.y, 0);
vert3 = vert2+Vector3(size.x, 0, 0);
vert4 = vert3-Vector3(0, size.y, 0);
verts.Add(vert1);
verts.Add(vert2);
verts.Add(vert3);
verts.Add(vert4);
tris.Add(verts.length - 4);
tris.Add(verts.length - 3);
tris.Add(verts.length - 2);
tris.Add(verts.length - 4);
tris.Add(verts.length - 2);
tris.Add(verts.length - 1);
normals.Add(-Vector3.forward);
normals.Add(-Vector3.forward);
normals.Add(-Vector3.forward);
normals.Add(-Vector3.forward);
}
//Y-axis faces*

* if(y == height-1 || !List[x, Mathf.Min(y+1, height-1), z].visible){
vert1 = position+(0.5size);

* vert2 = vert1-Vector3(0, 0, size.z);
vert3 = vert2-Vector3(size.x, 0, 0);
vert4 = vert3+Vector3(0, 0, size.z);
verts.Add(vert1);
verts.Add(vert2);
verts.Add(vert3);
verts.Add(vert4);
tris.Add(verts.length - 4);
tris.Add(verts.length - 3);
tris.Add(verts.length - 2);
tris.Add(verts.length - 4);
tris.Add(verts.length - 2);
tris.Add(verts.length - 1);
normals.Add(Vector3.up);
normals.Add(Vector3.up);
normals.Add(Vector3.up);
normals.Add(Vector3.up);
}
if(y == 0 || !List[x, Mathf.Max(y-1, 0), z].visible){
vert1 = position-(0.5size);

* vert2 = vert1+Vector3(0, 0, size.z);
vert3 = vert2+Vector3(size.x, 0, 0);
vert4 = vert3-Vector3(0, 0, size.z);
verts.Add(vert1);
verts.Add(vert2);
verts.Add(vert3);
verts.Add(vert4);
tris.Add(verts.length - 4);
tris.Add(verts.length - 2);
tris.Add(verts.length - 3);
tris.Add(verts.length - 4);
tris.Add(verts.length - 1);
tris.Add(verts.length - 2);
normals.Add(-Vector3.up);
normals.Add(-Vector3.up);
normals.Add(-Vector3.up);
normals.Add(-Vector3.up);
}
}
}
}
}*_

* var mesh = new Mesh();*
* mesh.vertices = VectorsToList(verts);*
* mesh.triangles = IntsToList(tris);*
* mesh.normals = VectorsToList(normals);*
* meshes.Add(mesh);*
* }*
* }*
* }*
* return meshes;*
* }*

* //Create Voxel Array*
* function CreateVoxelArray(vis : boolean){*
* for (var x : int = 0; x < width; x++){*
* for (var y : int = 0; y < height; y++){*
* for(var z : int = 0; z < depth; z++){*
_ var posX : float = origin.x + (x+0.5)defaultSize.x;
var posY : float = origin.y + (y+0.5)defaultSize.y;
var posZ : float = origin.z + (z+0.5)defaultSize.z;
var pos = Vector3(posX, posY, posZ);

List[x, y, z] = new Voxel(pos, defaultSize, defaultMaterial, vis);
}
}
}
}
public function VoxelArray(x : int, y : int, z : int, voxelSize : Vector3, voxelMaterial : VoxelMaterial, visible : boolean){
width = x;
height = y;
depth = z;*_

* defaultSize = voxelSize;*
* defaultMaterial = voxelMaterial;*

* List = new Voxel[width, height, depth];*
* CreateVoxelArray(visible);*
* }*
}
Test Script
-----------
var width = 10;
var height = 1;
var depth = 10;

var voxelList : VoxelArray;
var meshes : Array;
var material : Material;

function Start () {
* voxelList = new VoxelArray(width, height, depth, Vector3(1, 1, 1), VoxelMaterial.Air, false);*
* for(var x : int = 0; x < width; x++){*
* for (var y : int = 0; y < height; y++){*
* for(var z : int = 0; z < depth; z++){*
* var pos = voxelList.List[x, y, z].position;*
* var size = voxelList.List[x, y, z].size;*
* voxelList.List[x, y, z] = new Voxel(pos, size, VoxelMaterial.Stone, true);*
* }*
* }*
* }*
* meshes = VoxelArray.CreateMesh(voxelList);*
* for(var i : int = 0; i < meshes.length; i++){*
* var voxelBlock : GameObject;*
* voxelBlock = new GameObject ("VoxelBlock " + (i+1));*
* var mesh = voxelBlock.AddComponent(“MeshFilter”);*
* var renderer = voxelBlock.AddComponent(“MeshRenderer”);*
_ mesh.mesh = meshes*;
renderer.material = material;
}
}*

Enjoy!
Scribe_