local function IsDescendantOfCharacter(part)
local ancestor = part
while ancestor and ancestor.Parent do
if ancestor:IsA("Model") and Players:GetPlayerFromCharacter(ancestor) then
return true
end
ancestor = ancestor.Parent
end
return false
end
local function InSameModel(partA, partB)
local rootA = partA:FindFirstAncestorOfClass("Model")
local rootB = partB:FindFirstAncestorOfClass("Model")
return rootA and rootA == rootB
end
local function CacheKeyExists(partA, partB)
local cacheA = WeldCache[partA]
local cacheB = WeldCache[partB]
return (cacheA and cacheA[partB]) or (cacheB and cacheB[partA])
end
local function CacheKeyAdd(partA, partB)
WeldCache[partA] = WeldCache[partA] or setmetatable({}, { __mode = "k" })
WeldCache[partA][partB] = true
WeldCache[partB] = WeldCache[partB] or setmetatable({}, { __mode = "k" })
WeldCache[partB][partA] = true
end
local function CheckIfCanWeld(partA, partB)
if partA == partB then return false end
if CacheKeyExists(partA, partB) then return false end
if InSameModel(partA, partB) then return false end
for _, weld in ipairs(partB:GetChildren()) do
if weld:IsA("WeldConstraint") then
if (weld.Part0 == partA and weld.Part1 == partB) or (weld.Part0 == partB and weld.Part1 == partA) then
CacheKeyAdd(partA, partB)
return false
end
end
end
return true
end
local function CreateWeld(partA, partB)
if IsDescendantOfCharacter(partA) or IsDescendantOfCharacter(partB) then
DebugPrint("Skipped welding character part:", partA.Name, partB.Name)
return
end
if CheckIfCanWeld(partA, partB) then
local weld = Instance.new("WeldConstraint")
weld.Part0 = partA
weld.Part1 = partB
weld.Parent = partA
CacheKeyAdd(partA, partB)
DebugPrint("Welded:", partA.Name, "<->", partB.Name)
end
end
local function SurfaceWeldPart(part)
if not part:IsA("BasePart") then return end
Params.FilterDescendantsInstances = { part }
local partsNearby = workspace:GetPartBoundsInBox(part.CFrame, part.Size + OffsetVector, Params)
for _, nearbyPart in ipairs(partsNearby) do
CreateWeld(part, nearbyPart)
end
end
function SurfaceWeldModule.WeldPart(part)
SurfaceWeldPart(part)
end
function SurfaceWeldModule.WeldModel(model)
for _, part in ipairs(model:GetDescendants()) do
SurfaceWeldPart(part)
end
end
function SurfaceWeldModule.WeldParts(partsArray)
for _, part in ipairs(partsArray) do
SurfaceWeldPart(part)
end
end
function SurfaceWeldModule.ClearWelds(target)
local parts = {}
if typeof(target) == "Instance" then
parts = target:GetDescendants()
elseif typeof(target) == "table" then
parts = target
end
for _, part in ipairs(parts) do
if part:IsA("BasePart") then
for _, child in ipairs(part:GetChildren()) do
if child:IsA("WeldConstraint") then
child:Destroy()
DebugPrint("Destroyed weld on:", part.Name)
end
end
end
end
end
function SurfaceWeldModule.ClearCache()
table.clear(WeldCache)
DebugPrint("Cleared WeldCache")
end
function SurfaceWeldModule.SetDebug(state)
DEBUG = state
end
My welding module welds any parts that are touching each other whenever a block is placed. It has a weld cache system for parts and it uses workspace:GetPartBoundsInBox()
to find touching parts.
I tried placing a lot of blocks to see how much it can handle, and it starts causing performance issues at around 300 blocks if they are placed inside each other. If they are placed ontop of each other it doesnt lag as much at around 1,000 blocks but when the player zooms in it causes lag.
I would like suggestions on how I can improve this so it causes minimal lag even if a lot of blocks are welded.