I made an infinite mining generation script from a tutorial for my mining game, but it’s horribly optimized and I don’t know how exactly to optimize it. If someone mines for a bit eventually the amount of existing blocks and values start lagging the game for every block you mine.
So far I’ve looked into occlusion culling but that wouldn’t work as it would probably not help with performance if it keeps checking what objects are on screen, another thing I’ve tried is changing how the blocks and values get stored, but that ended up causing more lag, and so I’m just kind of stumped at this point I don’t know how to optimize this.
This is my code right now
local RS = game:GetService("ReplicatedStorage")
local positions = {
Vector3.new(6,0,0);
Vector3.new(-6,0,0);
Vector3.new(0,6,0);
Vector3.new(0,-6,0);
Vector3.new(0,0,6);
Vector3.new(0,0,-6);
}
local oreTable = {}
for i, v in ipairs(game.ServerStorage.Ores:GetChildren()) do
if v:IsA("Part") then
table.insert(oreTable, {ore = v, chance = v.Chance.Value})
end
end
local rollTable = {}
for _, data in ipairs(oreTable) do
for i = 1, data.chance, 1 do
table.insert(rollTable, data)
end
end
function Generate(pos)
if pos then
for _,pos2 in pairs(positions) do
local newPos = pos+pos2
local previouslyGenerated
for _,generated in pairs(workspace.Cubes.Generated:GetChildren()) do
if generated.Value == newPos then
previouslyGenerated = true
end
end
if newPos.Y > 0 then
previouslyGenerated = true
end
if not previouslyGenerated then
local random = math.random(1, #rollTable)
local ore = rollTable[random].ore:Clone()
ore.Position = newPos
ore.Parent = workspace.Cubes
RS.BlockGen.OnServerEvent:Connect(function(plr, rPart)
Generate(rPart.Position)
rPart:Destroy()
end)
local val = Instance.new("Vector3Value")
val.Value = newPos
val.Parent = workspace.Cubes.Generated
end
end
end
end
for i,cube in pairs(workspace.Cubes:GetChildren()) do
if cube:IsA("Part") then
local val = Instance.new("Vector3Value")
val.Value = cube.Position
val.Parent = workspace.Cubes.Generated
RS.BlockGen.OnServerEvent:Connect(function(plr, rPart)
Generate(rPart.Position)
rPart:Destroy()
end)
end
end
There’s a lot of things to optimize in this script that only you can do. With only little knowledge of your script, all I can really do is make it pretty:
-- services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- tables
local Positions = {
Vector3.new(6,0,0);
Vector3.new(-6,0,0);
Vector3.new(0,6,0);
Vector3.new(0,-6,0);
Vector3.new(0,0,6);
Vector3.new(0,0,-6);
}
local OreTable = {}
local RollTable = {}
-- for loops
for Index, Inst in ipairs(game.ServerStorage.Ores:GetChildren()) do
if Inst:IsA("Part") then
table.insert(OreTable, {ore = Inst, chance = Inst.Chance.Value})
end
end
for Index, Data in ipairs(OreTable) do
for i = 1, Data.chance, 1 do
table.insert(RollTable, Data)
end
end
-- main functions
function Generate(Position)
if Position then
for _, Position2 in pairs(Positions) do
local NewPosition = Position+Position2
local previouslyGenerated
for _, Generated in pairs(workspace.Cubes.Generated:GetChildren()) do
if Generated.Value == NewPosition then
previouslyGenerated = true
end
end
if NewPosition.Y > 0 then
previouslyGenerated = true
end
if not previouslyGenerated then
local random = math.random(1, #RollTable)
local ore = RollTable[random].ore:Clone()
ore.Position = NewPosition
ore.Parent = workspace.Cubes
ReplicatedStorage.BlockGen.OnServerEvent:Connect(function(plr, rPart)
Generate(rPart.Position)
rPart:Destroy()
end)
local Vector = Instance.new("Vector3Value")
Vector.Value = NewPosition
Vector.Parent = workspace.Cubes.Generated
end
end
end
end
for Index,Cube in pairs(workspace.Cubes:GetChildren()) do
if Cube:IsA("Part") then
local Vector = Instance.new("Vector3Value")
Vector.Value = Cube.Position
Vector.Parent = workspace.Cubes.Generated
ReplicatedStorage.BlockGen.OnServerEvent:Connect(function(plr, rPart)
Generate(rPart.Position)
rPart:Destroy()
end)
end
end
You shouldn’t connect this event in the for loop, this will repeatedly connect the same event even though it only needs to be connected once. Move it to the bottom of the script.
By the looks of it (assuming this is voxels) you aren’t implementing any form of greedy meshing, which means that you are rendering triangles for every block instead of greedy meshing it.
@/5uphi 's video explains greedy meshing pretty well
From what I understand by skimming through the tutorials, what this does is merge the blocks into one giant block as opposed to many tiny blocks, right? This isn’t what I’m looking for as the player might wanna go back into previous sections of the mine where presumably the blocks might be merged, and they can’t mine it anymore of course. Though you are correct it is voxels.
It did optimize my game a lot though by removing the event in the for loop. I still feel like the game lags just a little bit when I go past a certain point while mining.
You would just have to recalculate the greedy mesh for that specific area when the player mines/places a block. This is how every voxel game including Minecraft does it. Making and optimising a voxel game is a surprisingly complicated topic, I’d recommend you give these a read.