So I made a Voronoi diagram in Roblox Studio using parts and a script obviously. I need help optimising it.
Script
SEED = workspace:WaitForChild("SEED").Value
X, Z = 100, 100
-- defines the folders for the parts
local one = Instance.new("Folder"); one.Name = "1"; one.Parent = workspace
local two = Instance.new("Folder"); two.Name = "2"; two.Parent = workspace
local three = Instance.new("Folder"); three.Name = "3"; three.Parent = workspace
local four = Instance.new("Folder"); four.Name = "4"; four.Parent = workspace
-- generates a grid of parts
local function genGrid(X, Z)
for z = 1, Z do
for x = 1, X do
local p = Instance.new("Part")
p.Size = Vector3.new(1.01, 1.01, 1.01)
p.Position = Vector3.new(x, 0, z)
p.Anchored = true
p.Parent = workspace
if p.Position.X <= X/2 and p.Position.Z <= Z/2 then
p.Parent = one
end
if p.Position.X <= X/2 and p.Position.Z >= Z/2 then
p.Parent = two
end
if p.Position.X >= X/2 and p.Position.Z <= Z/2 then
p.Parent = three
end
if p.Position.X >= X/2 and p.Position.Z >= Z/2 then
p.Parent = four
end
end
end
end
-- adds a random dot onto the grid (colors one of the parts black)
randomDots = {}
math.randomseed(SEED)
local function createRandomDot(folder)
local cube = math.random(1, #workspace:WaitForChild(folder):GetChildren())
local part
for i,v in ipairs(workspace:WaitForChild(folder):GetChildren()) do
if i == cube then
part = v
break
end
end
part.Color = Color3.fromRGB( math.random(55, 255), math.random(55, 255), math.random(55, 255) )
table.insert(randomDots, part)
end
-- expands area of biome
local function initVoronoi()
local newDots = {}
for i,v in next, randomDots do
for i2, v2 in pairs(v:GetTouchingParts()) do
if v2.Color == Color3.fromRGB(163, 162, 165) then
v2.Color = v.Color
table.insert(newDots, v2)
end
end
end
randomDots = newDots
end
genGrid(X, Z)
createRandomDot(1)
createRandomDot(2)
createRandomDot(3)
createRandomDot(4)
createRandomDot(1)
createRandomDot(2)
createRandomDot(3)
createRandomDot(4)
while wait() do
initVoronoi()
end
Even with the changes I tried I saw no difference between mine and your code in terms of performance, the only thing that could cause some slowdowns is your use of wait(), as it is unreliable and is bad usage unless you use larger numbers than the default, you could try using one of RunService’s events instead, but that could be its own issue as it would be tied to the server’s framerate, so I think you could try using this custom wait
Anyways, I went through your code as saw things that would definitely help make it more shorter and readable
My revised code
local SEED = workspace:WaitForChild("SEED").Value
local X, Z = 100, 100
-- defines the folders for the parts
local one = Instance.new("Folder"); one.Name = "1"; one.Parent = workspace
local two = Instance.new("Folder"); two.Name = "2"; two.Parent = workspace
local three = Instance.new("Folder"); three.Name = "3"; three.Parent = workspace
local four = Instance.new("Folder"); four.Name = "4"; four.Parent = workspace
local randomDots = {}
math.randomseed(SEED)
-- generates a grid of parts
local function genGrid(X, Z)
for z = 1, Z do
for x = 1, X do
local part = Instance.new("Part")
part.Size = Vector3.new(1.01, 1.01, 1.01)
part.Position = Vector3.new(x, 0, z)
part.Anchored = true
if part.Position.X <= X/2 then
part.Parent = part.Position.Z <= Z/2 and one or two
else
part.Parent = part.Position.Z <= Z/2 and three or four
end
end
end
end
-- adds a random dot onto the grid (colors one of the parts black)
local function createRandomDot(folder)
folder = tostring(folder)
local cube = math.random(#workspace[folder]:GetChildren())
local part
for index, child in ipairs(workspace[folder]:GetChildren()) do
if index ~= cube then
continue
end
part = child
break
end
part.Color = Color3.fromRGB(math.random(55, 255), math.random(55, 255), math.random(55, 255))
table.insert(randomDots, part)
end
-- expands area of biome
local function initVoronoi()
local newDots = {}
for _, dot in ipairs(randomDots) do
for _, touching in ipairs(dot:GetTouchingParts()) do
if touching.Color ~= Color3.fromRGB(163, 162, 165) then
continue
end
touching.Color = dot.Color
table.insert(newDots, touching)
end
end
randomDots = newDots
end
genGrid(X, Z)
for _ = 1, 2 do
for dot = 1, 4 do
createRandomDot(dot)
end
end
while true do
wait()
initVoronoi()
end
My explanations
It’s common nowadays to localized every variable you plan to use globally across your code, as it is slightlyyyyyyyyy (very unnoticable) faster, but generally it’s just used because everyone uses it so I made your variables local and to make it uniform with your functions, as you localize those
I made your variable names more descriptive to help you and readers understand what they contain, example, I turned v in your initVoronoi function to dot, as it is in a randomDots table, p to part and so on. Being descriptive is the best thing you can do for yourself and others
The way you set up which parent t he part belongs to is weird, no more than 1 condition is ever going to be met unless the position coincidentally exactly matches the half of one of the axis, which will make it go through all of them, which I’ve shortened using a combination of an if-else and a fake tenary,
local variable = condition and (condition true) or (condition false)
I removed your WaitForChilds as they’re not needed as everything you’re waiting for has already been made by the time the script runs
I used a for loop to remove your code duplication for createRandomDot
I removed the parameters for your genGrid function as the function can alreayd see what you’re passing in
*And some other things that don’t really need to be mentioned such as turning your next into an ipairs and making your while wait() do to a while true do with a wait() inside
Should hopefully still work exactly as how you intended
@ocula Thanks for mentioning you could for loop the numbers too, my 8pm brain forgot to notice that
As mentioned by @MightyPart, a for loop could improve the cleanliness of your code. It would have no difference in performance either. If anything, it’s a much cleaner way of organizing the way in which your code is structured.