So my map is the recreation of the infinity castle. dynamic gravity, movement, and precedural generation using a seed (no 2 servers have the same layout)
The code for the map generation is optimized and the map takes 10 seconds to generate.
The gravity change script is optimized perfectly too using a chunk based system
The map uses these assets:
4 Different Walls
4 Different Doorways
2 Different Floors
1 Roof
2 Different Pillars
1 Fence
1 Item (Lantern)
1 Stair
This is used to generate the map itself
However its extremely laggy, Looking away from the map into the void gives me 230 Fps and looking upwards to the map from the bottom puts that down to 80-90 fps
Any tips on optimization?
I tried making my own chunk render system but it doesnt solve the issue
local MapControl = {}
local Update = game:GetService("RunService")
local Tween = game:GetService("TweenService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Collection = game:GetService("CollectionService")
local player = Players.LocalPlayer
local character = player.Character
local humanoid = character.Humanoid
local root = character.HumanoidRootPart
local remotes = ReplicatedStorage.Shared.Remotes
local handlers = script.Parent
local map = workspace:WaitForChild("Map")
local objects = ReplicatedStorage:WaitForChild("MapObjects")
local container = map:WaitForChild("Container")
local cubed_length = container.Size.Y
local room_length = 50
local rendered_chunks = {}
local grid = {} -- chunk -> objects
local gridKeys = {}
local batchedgridKeys = {} -- array of chunk keys for batching
local rendered_chunks = {}
local batchSize = 35 -- number of chunks to process per frame
local batchIndex = 1 -- current position in gridKeys
MapControl.batchedObjects = {}
local objectupdateCheck = 0.1
local objectbatch = 1
local objectbatch_size = 25
local renderDistance = 5
function MapControl.RenderObjectByDistance()
Update.PostSimulation:Connect(function()
if #gridKeys == 0 then return end
local pos = root.Position
local cX,cY,cZ = math.floor(pos.X/room_length), math.floor(pos.Y/room_length), math.floor(pos.Z/room_length)
for i = #batchedgridKeys, math.max(1,#batchedgridKeys-batchSize),-1 do
local key = batchedgridKeys[i]
local v = grid[key]
if v then
local split = string.split(key,":")
local x,y,z = tonumber(split[1]), tonumber(split[2]), tonumber(split[3])
if math.abs(x-cX) <= renderDistance and math.abs(y-cY) <= renderDistance and math.abs(z-cZ) <= renderDistance then
if #v > 0 and not rendered_chunks[key] then
rendered_chunks[key] = true
coroutine.wrap(function()
for _, v2 in ipairs(v) do
if v2 and v2.Parent and v2.Parent ~= map and rendered_chunks[key] == true then
v2.Parent = map
end
end
end)()
end
else
if #v > 0 and rendered_chunks[key] then
rendered_chunks[key] = nil
coroutine.wrap(function()
for _, v2 in ipairs(v) do
if v2 and v2.Parent and v2.Parent ~= ReplicatedStorage and rendered_chunks[key] == nil then
v2.Parent = ReplicatedStorage
end
end
end)()
end
end
end
table.remove(batchedgridKeys,i)
end
if #batchedgridKeys <= 0 then
batchedgridKeys = table.clone(gridKeys)
end
end)
end
function MapControl.AddChunk(object)
coroutine.wrap(function()
task.wait()
if object.PrimaryPart then
local pos = object.PrimaryPart.Position
local chunk = math.floor(pos.X/room_length)..":"..math.floor(pos.Y/room_length)..":"..math.floor(pos.Z/room_length)
if not grid[chunk] then
grid[chunk] = {}
table.insert(gridKeys, chunk)
rendered_chunks[chunk] = true
end
rendered_chunks[chunk] = true
table.insert(grid[chunk], object)
end
end)()
end
function MapControl:BatchSorting()
local timed = 0
Update.PostSimulation:Connect(function(delta)
timed += delta
if timed >= objectupdateCheck then
timed = 0
for i = #MapControl.batchedObjects, math.max(1,#MapControl.batchedObjects-objectbatch_size), -1 do
local object = MapControl.batchedObjects[i]
if object and object.Parent then
MapControl.AddChunk(object)
table.remove(MapControl.batchedObjects,i)
else
table.remove(MapControl.batchedObjects,i)
end
end
end
end)
end
for _, object in pairs(Collection:GetTagged("DistancedRender")) do
if object and object.Parent then
table.insert(MapControl.batchedObjects,1,object)
end
end
Collection:GetInstanceAddedSignal("DistancedRender"):Connect(function(object)
table.insert(MapControl.batchedObjects,1,object)
end)
MapControl:BatchSorting()
MapControl.RenderObjectByDistance()
return MapControl









