Attacher allows you to quickly and easily weld one model to another using attachments. It also allows the ability to track attached models via CollectionService, so that when either model is removed, the corresponding model will be cleaned up (weld removed). I originally created this for a game where a custom tool and wearable system is used.
Making models compatible with this system is easy. Simply create an attachment somewhere on both models, name them whatever you want, and that’s it.
Example
local Attachment = Attacher:Attach(MainModel.PrimaryPart, MainModel.MeshPart.AttachPoint, Character.Head, Character.Head:WaitForChild("HatAttach"));
print(Attachment.Part1, Attachment.Part2, Attachment.MainWeld)
Attachment:Destroy();
- The first parameter, TargetPart1, is the part in the first model which will take the weld. In this case, PrimaryPart would be MainModel.MeshPart
- Parameter 2 is the first attachment.
- Parameter 3 is the part that will be used for welds in the second model.
- Parameter 4 is the attachment in the second model. In this case, I made a custom attachment in the
head named “HatAttach”
Model 1 will now be welded to Model 2.
if TRACK_ATTACHMENTS is set to true, if Model 1 is destroyed, Model 2 will have anything created by Attacher destroyed, and vice versa. It is recommended to keep this enabled.
Attach returns a table with a Destroy method, and three properties. Part1, Part2, and MainWeld
Module
--[[
Voidage
Attacher allows easy welding between two models via attachments.
Example (Attach MainModel, a hat, to the head):
local Attachment = Attacher:Attach(MainModel.PrimaryPart, MainModel.MeshPart.AttachPoint, Character.Head, Character.Head:WaitForChild("HatAttach"));
print(Attachment.Part1, Attachment.Part2, Attachment.MainWeld)
Attachment:Destroy();
--
TRACK_ATTACHMENTS help
true: models which have been attached to each other will be tracked with collectionservice.
when either model is destroyed, associated parts/welds with the other model will be destroyed.
]]--
local TRACK_ATTACHMENTS = true;
local CollectionService = game:GetService("CollectionService");
local WeldPart = Instance.new("Part");
WeldPart.Name = "WELDPART";
WeldPart.CanQuery = false;
WeldPart.CanCollide = false;
WeldPart.CanTouch = false;
WeldPart.Anchored = false;
WeldPart.Massless = true;
WeldPart.Size = Vector3.new(0.25, 0.25, 0.25);
WeldPart.Transparency = 1;
local Attacher = {};
Attacher.Attachments = {};
function Attacher:Clear(Part: any)
if Part:FindFirstChild("WELDPART") ~= nil then
if Part.WELDPART.Brother.Value ~= nil then
Part.WELDPART.Brother.Value:Destroy();
end
Part.WELDPART:Destroy();
end
local intable = Attacher.Attachments[Part];
if intable ~= nil then
if intable[1] ~= nil then
intable[1]:Destroy();
end
Attacher.Attachments[Part] = nil;
end
end
function Attacher:Attach(TargetPart1: BasePart, Attach1: Attachment, TargetPart2: BasePart, Attach2: Attachment)
if TargetPart1:FindFirstChild("WELDPART") ~= nil then
Attacher:Clear(TargetPart1);
end;
local WeldPart1 = WeldPart:Clone();
local WeldPart2 = WeldPart:Clone();
WeldPart1.CFrame = Attach1.WorldCFrame;
WeldPart2.CFrame = Attach2.WorldCFrame;
local weld1 = Instance.new("WeldConstraint");
weld1.Part0 = WeldPart1;
weld1.Part1 = TargetPart1;
weld1.Parent = WeldPart1;
local weld2 = Instance.new("WeldConstraint");
weld2.Part0 = WeldPart2;
weld2.Part1 = TargetPart2;
weld2.Parent = WeldPart2;
local Weld1Brother = Instance.new("ObjectValue");
Weld1Brother.Name = "Brother";
Weld1Brother.Value = WeldPart2;
Weld1Brother.Parent = WeldPart1;
local Weld2Brother = Instance.new("ObjectValue");
Weld2Brother.Name = "Brother";
Weld2Brother.Value = WeldPart1;
Weld2Brother.Parent = WeldPart2;
WeldPart1.Parent = TargetPart1;
WeldPart2.Parent = TargetPart2;
WeldPart1.CFrame = Attach2.WorldCFrame;
local Weld = Instance.new("WeldConstraint");
Weld.Part0 = WeldPart1;
Weld.Part1 = WeldPart2;
Weld.Parent = WeldPart1;
if TRACK_ATTACHMENTS then
CollectionService:AddTag(TargetPart1, "AttacherTracked");
CollectionService:AddTag(TargetPart2, "AttacherTracked");
Attacher.Attachments[TargetPart1] = {WeldPart2};
Attacher.Attachments[TargetPart2] = {WeldPart1};
end
local AttachTable = {Part1 = TargetPart1, Part2 = TargetPart2, MainWeld = Weld};
function AttachTable:Destroy()
if WeldPart1 ~= nil then WeldPart1:Destroy() end;
if WeldPart2 ~= nil then WeldPart2:Destroy() end;
if TRACK_ATTACHMENTS then
Attacher:Clear(TargetPart1);
Attacher:Clear(TargetPart2);
end
end
return AttachTable;
end
-- Detect when tracked attachers are removed
if TRACK_ATTACHMENTS then
CollectionService:GetInstanceRemovedSignal("AttacherTracked"):Connect(function(Model)
Attacher:Clear(Model);
end)
end
return Attacher;
update 1: made tracking more reliable with “brother” objectvalues for weldparts to work with collectionservice as well