Hello! I was wondering how I could reduce the lag in a world where all of the blocks on land are randomly generated. The problem is, there are thousands of parts that cause a ton of lag when the world loads. I have tried using the greedy mesher tutorial, but I don’t understand how I can use it in the game since the greedy mesher tutorial only shows how to do it in a single “type” and it is a little confusing. I was wondering how you could do it with multiple types of blocks (Like grass,dirt,stone) and still be able to destroy and place blocks.
You could go for the Minecraft approach, and basically just use chunks for random-generation. This is a little complicated to do but it should do the job nicely.
Basically, in Minecraft, chunks are 16x16 spaces of the world. What you’ll do is basically make it so that every chunk is loaded relative to the distance of the player.
I don’t really want to go too into detail, so here is the official Minecraft wiki page on Chunk loading.
To reduce the lag, what you’ll want to is to create some sort of table that contains all the loaded chunks.
The chunks for all the players are loaded locally to reduce the stress on the server. Whenever a player moves around, it will load chunks for them relative to its position, and will then proceed to unload certain chunks that are too far.
If you’re gonna go my route you’re gonna have to reduce the chunk rendering to around 2 or maybe even up to 4. Roblox is fairly capable handling massive amounts of parts, however considering how many blocks can be filled within a 16x16x16 space, I think that 4 is the maximum you can go.
Yes, however it makes the game almost unplayable for the moments when chunks are loading in because of the amount of parts, this could be made faster with a greedy mesher that converts nearby parts into 1 part which makes it significantly easier to load chunks. The problem is, I do not know how to implement this into my game which has multiple types of blocks.
This may sound stupid, but I guess you can make the Greedy Mesher just check the parts adjacent to it if they’re the same type before merging together. For actual destruction and placing systems, I have no idea how to implement.
Woah woah woah you shouldn’t be loading in EVERY single part generated by the algorithm!
Take a tip from Minecraft and only generate what you need visible. Ok well in Minecraft they just merge everything into one mesh, which you could theoretically do with unions but that’s too slow.
You could just generate the visible parts needed by checking if the adjacent blocks to the one you just mined/generated and see if it’s visible. Try taking apart bereza12’s Azure Mines open source kit for something like this. It generates the blocks that are visible, not all of the blocks.
The way that they use it in the mine is different since the mine is completely flat and all they have to do is when the player mines, just add parts surrounding it. The problem is that it’s hard to tell which parts are visible and which ones are not and there could be holes in the map, so I don’t think this method could work.
The only blocks that can be reached/seen are the ones on the very surface of the solid volume. Every block has 6 neighbors. A block on the boundary between air and solid blocks has a combination of neighbors that are air and solid. So adding a check to see if it has both lets us only generate blocks on the boundary.
E.g.
function getCoordinateNeighbors(coordinate)
local r = {}
for _, nid in pairs(Enum.NormalId:GetEnumItems()) do
local dir = Vector3.FromNormalId(nid)
local n = coordinate + dir
table.insert(r, n)
end
return r
end
function isSolid(c)
return getHeightMapValue(c.X, c.Z) >= c.Y
end
function isAir(...)
return not isSolid(...)
end
function isOnBoundary(c)
local hasAirN, hasSolidN = false, false
local isBoundary = false
for _, n in pairs(getCoordinateNeighbors(c)) do
hasAirN = isAir(n) or hasAirN
hasSolidN = isSolid(n) or hasSolidN
if hasAirN and hasSolidN then
isBoundary = true
break
end
end
end
for x = 1, mapSize do
for z = 1, mapSize do
local y = 0
repeat
y += 1
local c = Vector3.new(x, y, z)
if isOnBoundary(c) then
--build block
end
until isAir(c)
end
end
What I did for my game is I made it so the player had like a square grid where it checked if there were voxels there. Or in this case terrain cells. If it did I would ignore it, else I would generate the terrain from the seed. To reduce lag what I did is I made it so that when you are x stuff away it deletes the trees. I noticed that terrain didn’t generate any lag but hey.