Here are some images of the server microprofiler:
Here is an image of these 7 things closer (They are pretty much the same)
Here is some big thing that takes up to 1600 ms frame times, I think this is the problem, since it uses a lot of cpu and it isn’t stacked like your image:
I can also send you the HTML if you would need it
This is the terrain script:
local Emitter = script.Parent.Emitter
local Receiver = script.Parent.Receiver
function PerlinNoise(coords,amplitude,octaves,persistence)
coords = coords or {}
octaves = octaves or 1
persistence = persistence or 0.5
if #coords > 4 then
error("The Perlin Noise API doesn't support more than 4 dimensions!")
else
if octaves < 1 then
error("Octaves have to be 1 or higher!")
else
local X = coords[1] or 0
local Y = coords[2] or 0
local Z = coords[3] or 0
local W = coords[4] or 0
amplitude = amplitude or 10
octaves = octaves-1
if W == 0 then
local perlinvalue = (math.noise(X/amplitude,Y/amplitude,Z/amplitude))
if octaves ~= 0 then
for i = 1,octaves do
perlinvalue = perlinvalue+(math.noise(X/(amplitude*(persistence^i)),Y/(amplitude*(persistence^i)),Z/(amplitude*(persistence^i)))/(2^i))
end
end
return perlinvalue
else
local AB = math.noise(X/amplitude,Y/amplitude)
local AC = math.noise(X/amplitude,Z/amplitude)
local AD = math.noise(X/amplitude,W/amplitude)
local BC = math.noise(Y/amplitude,Z/amplitude)
local BD = math.noise(Y/amplitude,W/amplitude)
local CD = math.noise(Z/amplitude,W/amplitude)
local BA = math.noise(Y/amplitude,X/amplitude)
local CA = math.noise(Z/amplitude,X/amplitude)
local DA = math.noise(W/amplitude,X/amplitude)
local CB = math.noise(Z/amplitude,Y/amplitude)
local DB = math.noise(W/amplitude,Y/amplitude)
local DC = math.noise(W/amplitude,Z/amplitude)
local ABCD = AB+AC+AD+BC+BD+CD+BA+CA+DA+CB+DB+DC
local perlinvalue = ABCD/12
if octaves ~= 0 then
for i = 1,octaves do
local AB = math.noise(X/(amplitude*(persistence^i)),Y/(amplitude*(persistence^i)))
local AC = math.noise(X/(amplitude*(persistence^i)),Z/(amplitude*(persistence^i)))
local AD = math.noise(X/(amplitude*(persistence^i)),W/(amplitude*(persistence^i)))
local BC = math.noise(Y/(amplitude*(persistence^i)),Z/(amplitude*(persistence^i)))
local BD = math.noise(Y/(amplitude*(persistence^i)),W/(amplitude*(persistence^i)))
local CD = math.noise(Z/(amplitude*(persistence^i)),W/(amplitude*(persistence^i)))
local BA = math.noise(Y/(amplitude*(persistence^i)),X/(amplitude*(persistence^i)))
local CA = math.noise(Z/(amplitude*(persistence^i)),X/(amplitude*(persistence^i)))
local DA = math.noise(W/(amplitude*(persistence^i)),X/(amplitude*(persistence^i)))
local CB = math.noise(Z/(amplitude*(persistence^i)),Y/(amplitude*(persistence^i)))
local DB = math.noise(W/(amplitude*(persistence^i)),Y/(amplitude*(persistence^i)))
local DC = math.noise(W/(amplitude*(persistence^i)),Z/(amplitude*(persistence^i)))
local ABCD = AB+AC+AD+BC+BD+CD+BA+CA+DA+CB+DB+DC
perlinvalue = perlinvalue+((ABCD/12)/(2^i))
end
end
return perlinvalue
end
end
end
end
local availablePositions = {
Vector3.new(0, 1, 0),
Vector3.new(1, 0, 0),
Vector3.new(0, 0, 1),
Vector3.new(-1, 0, 0),
Vector3.new(0, 0, -1),
Vector3.new(0, -1, 0),
}
--task.desynchronize()
local function toRun(chunk, position, extras)
local chunkSize, seed, scale, amplitude, cave_scale, cave_amplitude = unpack(extras)
local blocks = table.create(chunkSize.X)
task.desynchronize()
for x = 1, chunkSize.X + 1 do
if not blocks[x] then blocks[x] = table.create(chunkSize.Z) end
local real_x = position.X * chunkSize.X + x
for z = 1, chunkSize.Z + 1 do
if not blocks[x][z] then blocks[x][z] = table.create(chunkSize.Y) end
local real_z = position.Z * chunkSize.Z + z
for y = 1, chunkSize.Y + 1 do
local real_y = position.Y * chunkSize.Y + y - 1
local cave_density = PerlinNoise({real_x, real_y, real_z, seed}, cave_scale) * cave_amplitude
local block = {
--position = Vector3.new(real_x, real_y, real_z),
material = "unknown",
}
if real_y > 3 then
if cave_density > 25 then
block.material = "air"
else
local density = y + PerlinNoise({real_x, real_y, real_z, seed}, scale, 4) * amplitude -- (amplitude + chunk.splineValue)
--if 150 > (density - chunk.splineValue) then
--if density < 130 then
if density < 135 then
block.material = "stone"
else
--block.light = 0
block.material = "air"
end
end
else
if real_y == 1 then
block.material = "barrier"
else
local barrier_density = (PerlinNoise({real_x, real_y, real_z, seed}, 5) * 100) + real_y
if math.abs(barrier_density) > 2 then
block.material = "barrier"
end
end
end
blocks[x][z][y] = block
end
end
--[[if x % 5 == 0 then
task.wait()
--task.desynchronize()
end]]
end
for x = 1, chunkSize.X + 1 do
for z = 1, chunkSize.Z + 1 do
for y = 1, chunkSize.Y + 1 do
local block = blocks[x][z][y]
if block.material ~= "air" then
--[[local topBlock = blocks[x][z][y + 1]
if not topBlock or topBlock.material == "air" then
block.visible = true
end]]
else
for _, position in ipairs(availablePositions) do
local real_x = x + position.X
local real_y = y + position.Y
local real_z = z + position.Z
if blocks[real_x] and blocks[real_x][real_z] then
local neighbor = blocks[real_x][real_z][real_y]
if neighbor and neighbor.material ~= "air" then
neighbor.visible = true
end
end
end
end
end
end
--[[if x % 5 == 0 then
task.wait()
--task.desynchronize()
end]]
end
return blocks
end
Receiver.Event:Connect(function(threadId, name, arguments)
local result = toRun(unpack(arguments))
Emitter:Fire(threadId, result)
end)
and this is how I’m creating the actors:
local ThreadManager = {}
local Thread = {}
Thread.__index = Thread
local HttpService = game:GetService("HttpService")
local ThreadsFolder = game:GetService("ServerScriptService"):FindFirstChild("Threads")
if not ThreadsFolder then
ThreadsFolder = Instance.new("Folder", game:GetService("ServerScriptService"))
ThreadsFolder.Name = "Threads"
end
function ThreadManager.new(threads)
threads = threads or 12
assert(typeof(threads) == "number", "The 'threads' argument must be a number")
assert(threads > 1, "You must chose at least 1 thread")
local threadObject = setmetatable({}, Thread)
threadObject.lastRun = 0
threadObject.threadNum = threads
threadObject.threads = {}
for i = 1, threads do
local newThread = script.Thread:Clone()
newThread.Parent = ThreadsFolder
table.insert(threadObject.threads, newThread)
end
return threadObject
end
function Thread:RunFunction(name, arguments, onFinished)
assert(typeof(name) == "string", "The 'name' argument must be a string")
assert(typeof(arguments) == "table", "The 'arguments' argument must be a table")
assert(typeof(onFinished) == "function" or typeof(onFinished) == "nil", "The 'onFinished' argument must be a function or nil")
--assert(script.Functions:FindFirstChild(name), "function not found")
self.lastRun += 1
if self.lastRun > self.threadNum then
self.lastRun = 1
end
local threadId = HttpService:GenerateGUID(false)
local threadUsing = self.threads[self.lastRun]
local emitterEvent ; emitterEvent = threadUsing.Emitter.Event:Connect(function(receivingId, ...)
if threadId == receivingId then
emitterEvent:Disconnect()
if onFinished then
onFinished(...)
end
end
end)
threadUsing.Receiver:Fire(threadId, name, arguments)
end
return ThreadManager
This is the structure of it:
I know it’s a lot to take in, but I don’t really understand how I’m supposed to fix this