Hey y’all! I’m working on a wall based system in which windows are placed and parts are created around the cut; however, too many parts are created so I’m trying to figure out how to combine similar and overlapping parts.

I’ve gotten my system to work when 0 degrees of rotation is present (3rd video try), but otherwise it either doesn’t combine parts (1st video try), or deletes them (2nd video try).

Any help would be massively appreciated! (P.S. sorry the code is so messy I was trying to get it to work before optimizing it)

Hi! I saw the video, and I think instead of creating a lot of parts and then merging them, you should merge the window parts beforehand. Then, when you insert a window, all you have to do would be to make the hole for the window and then clone and put the window in.

Also, using this method wouldn’t make you run into the rotational issues.

local function combine(model: Model)
task.wait(.5) -- temp
local parts = model:GetChildren()
for index,part in parts do
for index2,part2 in parts do
if (part) and (part2) and not (part == part2) then
if (part.Size.X == part2.Size.X) then
if (part.Position.X == part2.Position.X) and (part.Position.Z == part2.Position.Z) then
local isNextTo = math.round((part.Position.Y+(part.Size.Y/2)) - (part2.Position.Y-(part2.Size.Y/2))) == 0
local isOverlapping = table.find(workspace:GetPartsInPart(part), part2)
if (isNextTo or isOverlapping) then
local newPart = part:Clone()
newPart.Parent = model
newPart.Color = Color3.fromRGB(255, 0, 0)
local biggerLeft1 = (part2.Position.Y+(part2.Size.Y/2)) < (part.Position.Y-(part.Size.Y/2))
local biggerRight1 = (part2.Position.Y-(part2.Size.Y/2)) < (part.Position.Y-(part.Size.Y/2))
local biggerLeft2 = (part2.Position.Y+(part2.Size.Y/2)) > (part.Position.Y-(part.Size.Y/2))
local biggerRight2 = (part2.Position.Y-(part2.Size.Y/2)) > (part.Position.Y-(part.Size.Y/2))
if (biggerLeft1 and biggerRight1) or (biggerLeft2 and biggerRight2) then
part:Destroy()
part2:Destroy()
combine(model)
return
end
local size = part2.Position.Y > part.Position.Y and
(part2.Size.Y/2+part2.Position.Y)-(part.Size.Y/2+part.Position.Y) or
-((part.Position.Y-part.Size.Y/2)-(part2.Position.Y-part2.Size.Y/2))
newPart.Size += Vector3.new(0, math.abs(size), 0)
newPart.Position += Vector3.new(0, size/2, 0)
part:Destroy()
part2:Destroy()
combine(model)
return
end
end
end
if (math.round(part.Size.Y-part2.Size.Y) == 0) then
if (math.round(part.Position.Y-part2.Position.Y) == 0) and (math.round(part.Position.X-part2.Position.X) == 0) then
local isNextTo = math.round((part.Position.Z+(part.Size.Z/2)) - (part2.Position.Z-(part2.Size.Z/2))) == 0
local isOverlapping = table.find(workspace:GetPartsInPart(part), part2)
if (isNextTo or isOverlapping) then
local newPart = part:Clone()
newPart.Parent = model
newPart.Color = Color3.fromRGB(255, 0, 0)
local biggerLeft1 = (part2.Position.Z+(part2.Size.Z/2)) < (part.Position.Z-(part.Size.Z/2))
local biggerRight1 = (part2.Position.Z-(part2.Size.Z/2)) < (part.Position.Z-(part.Size.Z/2))
local biggerLeft2 = (part2.Position.Z+(part2.Size.Z/2)) < (part.Position.Z+(part.Size.Z/2))
local biggerRight2 = (part2.Position.Z-(part2.Size.Z/2)) < (part.Position.Z+(part.Size.Z/2))
if (biggerLeft1 and biggerRight1) or (biggerLeft2 and biggerRight2) then
part:Destroy()
part2:Destroy()
combine(model)
return
end
local size = part2.Position.Z > part.Position.Z and
(part2.Size.Z/2+part2.Position.Z)-(part.Size.Z/2+part.Position.Z) or
-((part.Position.Z-part.Size.Z/2)-(part2.Position.Z-part2.Size.Z/2))
newPart.Size += Vector3.new(0, 0, math.abs(size))
newPart.Position += Vector3.new(0, 0, size/2)
part:Destroy()
part2:Destroy()
combine(model)
return
end
elseif (math.round(part.Position.Y-part2.Position.Y) == 0) and (math.round(part.Position.Z-part2.Position.Z) == 0) then
local isNextTo = math.round((part.Position.X+(part.Size.Z/2)) - (part2.Position.X-(part2.Size.Z/2))) == 0
local isOverlapping = table.find(workspace:GetPartsInPart(part), part2)
if (isNextTo or isOverlapping) then
local newPart = part:Clone()
newPart.Parent = model
newPart.Color = Color3.fromRGB(255, 0, 0)
local biggerLeft1 = (part2.Position.X+(part2.Size.Z/2)) < (part.Position.X-(part.Size.Z/2))
local biggerRight1 = (part2.Position.X-(part2.Size.Z/2)) < (part.Position.X-(part.Size.Z/2))
local biggerLeft2 = (part2.Position.X+(part2.Size.Z/2)) > (part.Position.X-(part.Size.Z/2))
local biggerRight2 = (part2.Position.X-(part2.Size.Z/2)) > (part.Position.X-(part.Size.Z/2))
if (biggerLeft1 and biggerRight1) or (biggerLeft2 and biggerRight2) then
part:Destroy()
part2:Destroy()
combine(model)
return
end
local size = part2.Position.X > part.Position.X and
(part2.Size.Z/2+part2.Position.X)-(part.Size.Z/2+part.Position.X) or
-((part.Position.X-part.Size.Z/2)-(part2.Position.X-part2.Size.Z/2))
newPart.Size += Vector3.new(0, 0, math.abs(size))
newPart.Position += Vector3.new(size/2, 0, 0)
part:Destroy()
part2:Destroy()
combine(model)
return
end
end
end
end
end
end
end
combine(workspace.wall3)

The wall shown in the video is after the window-hole has been cut (with the actual window model not present). My cutting algorithm creates too many parts, hence the need to combine parts after the fact. After every ‘cut’ the combine algorithm should run. Unless I’m misunderstanding what you’re saying.