How to do I go about welding parts together depending if their surfaces are touching?

I am currently looking for an effective and fast way to weld hundreds of small blocks together that have their surfaces touching (wether the parts are welded or not) (pretty well the same way how the legacy surfaces joints worked)

What is the best way to do this?

If your parts are all rectangular and only rotated in 90-degree increments, something like this would work:

That thread has some more discussion as well.

if this uses regions to find other blocks (which is just a big box), does that mean it will weld blocks that are on the corners of other blocks?

Yeah, probably. You could make three separate Region3s that are narrower than the block except on one axis, but it would be more expensive (three times more, to be exact :slight_smile: ).

i.e. right now it’s doing this for each part (red is the region):

image

And you could change it to do this:

image

1 Like

You could also not use region3s for this.

If all your parts are axis-aligned, it’s pretty easy to implement intersection tests.

If they are rotated, you could either use the Rotated Region3 module I linked to in my linked post, or you could implement the separating axis theorem yourself, which that module probably uses internally anyways.

1 Like

Use GetPartBoundsInBox. Make the size parameter slightly larger than the part size.

2 Likes

Didn’t know that function existed, it’s definitely a better option!

1 Like

You can also use GetPartBoundsInRadius for spheres.

1 Like

@samtheblender and @nicemike40 thanks! All of your answers are great. all though the three regions or bounds method to avoid welding parts on corners doesn’t seem to work for me.

All tho it does weld perfectly fine when I use one bound or region. (but then the corners weld)

local SurfaceWeldModule = {}

local ServerScriptService = game:GetService("ServerScriptService")


local function WeldPart(Part)
	local Offset = 0.05
	
	local OffsetVectorX = Vector3.new(Offset, -Offset, -Offset)
	local OffsetVectorY = Vector3.new(-Offset, Offset, -Offset)
	local OffsetVectorZ = Vector3.new(-Offset, -Offset, Offset)
	
	local PartsX = workspace:GetPartBoundsInBox(Part.CFrame, Part.Size + OffsetVectorX)
	local PartsY = workspace:GetPartBoundsInBox(Part.CFrame, Part.Size + OffsetVectorY)
	local PartsZ = workspace:GetPartBoundsInBox(Part.CFrame, Part.Size + OffsetVectorZ)
	
	local PartsToWeld = {table.unpack(PartsX), table.unpack(PartsY), table.unpack(PartsZ)}
	
	for i, PartToWeldTo in pairs(PartsToWeld) do
		local Weld = Instance.new("WeldConstraint")
		Weld.Part1 = PartToWeldTo
		Weld.Part0 = Part
		Weld.Parent = Part
	end
end

function SurfaceWeldModule.WeldModel(Model)
	for i, Part in pairs(Model:GetDescendants()) do
		if Part:IsA("BasePart") then
			WeldPart(Part)
		end
	end
end

return SurfaceWeldModule

oh wait. never mind. It works.

It turns out using table.unpack within a table is really unreliable for some reason.

I edited the code and now it works perfectly!

local SurfaceWeldModule = {}

local ServerScriptService = game:GetService("ServerScriptService")

local Params = OverlapParams.new()
Params.FilterType = Enum.RaycastFilterType.Blacklist


local function WeldPart(Part)
	local Offset = 0.05
	
	Params.FilterDescendantsInstances = {Part}
	
	local OffsetVectorX = Vector3.new(Offset, -Offset, -Offset)
	local OffsetVectorY = Vector3.new(-Offset, Offset, -Offset)
	local OffsetVectorZ = Vector3.new(-Offset, -Offset, Offset)
	
	local PartsX = workspace:GetPartBoundsInBox(Part.CFrame, Part.Size + OffsetVectorX, Params)
	local PartsY = workspace:GetPartBoundsInBox(Part.CFrame, Part.Size + OffsetVectorY, Params)
	local PartsZ = workspace:GetPartBoundsInBox(Part.CFrame, Part.Size + OffsetVectorZ, Params)
	
	for i, PartToWeldTo in pairs(PartsX) do
		local Weld = Instance.new("WeldConstraint")
		Weld.Part1 = PartToWeldTo
		Weld.Part0 = Part
		Weld.Parent = Part
	end
	for i, PartToWeldTo in pairs(PartsY) do
		local Weld = Instance.new("WeldConstraint")
		Weld.Part1 = PartToWeldTo
		Weld.Part0 = Part
		Weld.Parent = Part
	end
	for i, PartToWeldTo in pairs(PartsZ) do
		local Weld = Instance.new("WeldConstraint")
		Weld.Part1 = PartToWeldTo
		Weld.Part0 = Part
		Weld.Parent = Part
	end
end

function SurfaceWeldModule.WeldModel(Model)
	for i, Part in pairs(Model:GetDescendants()) do
		if Part:IsA("BasePart") then
			WeldPart(Part)
		end
	end
end

return SurfaceWeldModule

Thanks for your help guys!

2 Likes