Cloning accessory from one humanoid to another isn't working as intended

To keep it brief, I want to locally clone the player’s outfit onto another dummy when the player fully loads. This means the shirt, pants, skin tone, face and accessories. The latter four work perfectly, it’s the accessories that are giving me issues.

I assume the issue has something to do with welds, since the accessory is cloning, but the accessory stays welded on the player’s head. The cloned accessory’s parent, however, is the dummy. It’s easily been 6 months since I’ve worked on this project, so it’s probably something really simple and I’m just overlooking it. Here’s the local script:

local Player = game:GetService("Players").LocalPlayer
local workspaceLocalPlayer = game.Workspace:WaitForChild(Player.Name);
local clone = game.Workspace["Random NPCS"]:WaitForChild("seatedOnTrain_Player");

-- code for rebuilding clone model
local function createJoint(jointName, att0, att1)
	local part0, part1 = att0.Parent, att1.Parent
	local newMotor = part1:FindFirstChild(jointName)

	if not (newMotor and newMotor:IsA("Motor6D")) then
		newMotor = Instance.new("Motor6D")
	end

	newMotor.Name = jointName

	newMotor.Part0 = part0
	newMotor.Part1 = part1

	newMotor.C0 = att0.CFrame
	newMotor.C1 = att1.CFrame

	newMotor.Parent = part1
end

local function buildJointsFromAttachments(part, characterParts)
	if not part then
		return
	end

	-- first, loop thru all of the part's children to find attachments
	for _, attachment in pairs(part:GetChildren()) do
		if attachment:IsA("Attachment") then
			-- only do joint build from "RigAttachments"
			local attachmentName = attachment.Name
			local findPos = attachmentName:find("RigAttachment")
			if findPos then
				-- also don't make double joints (there is the same named
				-- rigattachment under two parts)
				local jointName = attachmentName:sub(1, findPos - 1)
				if not part:FindFirstChild(jointName) then
					-- try to find other part with same rig attachment name
					for _, characterPart in pairs(characterParts) do
						if part ~= characterPart then
							local matchingAttachment = characterPart:FindFirstChild(attachmentName)
							if matchingAttachment and matchingAttachment:IsA("Attachment") then
								createJoint(jointName, attachment, matchingAttachment)
								buildJointsFromAttachments(characterPart, characterParts)
								break
							end
						end
					end
				end
			end
		end
	end
end

local function buildRigFromAttachments(humanoid)
	local rootPart = humanoid.RootPart
	assert(rootPart, "Humanoid has no HumanoidRootPart.")

	local characterParts = {}

	for _, descendant in ipairs(humanoid.Parent:GetDescendants()) do
		if descendant:IsA("BasePart") then
			table.insert(characterParts, descendant)
		end
	end

	buildJointsFromAttachments(rootPart, characterParts)
end


local function OnCharacterAdded(Character)
	Player.Archivable = true;
	wait(10);
	for _, accessory in pairs(workspaceLocalPlayer.Humanoid:GetAccessories()) do
		local clonedAccessory = accessory:Clone();
		clonedAccessory.Handle.Anchored = false;
		clone.Humanoid:AddAccessory(clonedAccessory);
	end
	
	-- so many if statements are here just in case a player doesn't have one of these
	if workspaceLocalPlayer:FindFirstChildWhichIsA("Shirt") then
		local clonedShirt = workspaceLocalPlayer:FindFirstChildWhichIsA("Shirt"):Clone();
		clonedShirt.Parent = clone;
	end
	if workspaceLocalPlayer:FindFirstChildWhichIsA("BodyColors") then
		local clonedBodyColors = workspaceLocalPlayer:FindFirstChildWhichIsA("BodyColors"):Clone();
		clonedBodyColors.Parent = clone;
	end
	if workspaceLocalPlayer:FindFirstChildWhichIsA("Pants") then
		local clonedPants = workspaceLocalPlayer:FindFirstChildWhichIsA("Pants"):Clone();
		clonedPants.Parent = clone;
	end
	if workspaceLocalPlayer.Head:FindFirstChildWhichIsA("Decal") then
		local clonedFace = workspaceLocalPlayer.Head:FindFirstChildWhichIsA("Decal"):Clone();
		clonedFace.Parent = clone.Head;
	end
	Player.Archivable = false;
	-- i thought this would be a fix to my issue but it didn't :(
	buildRigFromAttachments(clone:WaitForChild("Humanoid"))
end
if Player.Character then OnCharacterAdded(Player.Character) end
Player.CharacterAdded:Connect(OnCharacterAdded)

Here’s my model next to the dummy:
image
I used my sparkles as an example, i used the AddAccessory() and it added the accessory to the dummy but it’s still stuck on my head.
image
So how should I change my script above? Any help is greatly appreciated! Thank you so much <3

1 Like

You need to re-weld the accessory, and that may require calculations.

Some months ago, I created a character editor/creator Module. In order to attach the Accessories correctly to the character, I had to do some calculating.
I learned the calculations in this code from someone else, I believe. However, I forgot whom.

The first thing you’ll want to do is retrieve the Handle of the accessory, then its Attachment:

local handle = accessory.Handle

-- We don't know the name of the Attachment because we
-- don't know what kind of accessory the accessory is.
local attachment0 = handle:FindFirstChildOfClass("Attachment")

Inside the character you want to apply the accessory to, search for the body part that has an Attachment with the same Name as attachment0’s Name. You will need to use that body part and the Attachment.

(Every Accessory has an Attachment with the same name as one inside the character so that the Accessory can connect to the character’s Attachment.)

local attachment1 = character:FindFirstDescendant(attachment0.Name)
local bodyPart = attachment1.Parent

Then create a new Weld. This Weld will be used to hold the Accessory in the correct place (on the character).

local weld = Instance.new("Weld")
weld.Name = "AccessoryWeld"

Next, set the Weld’s Part0 to the Handle, Part1 to the body part; set the Weld’s C0 to attachment0’s CFrame, and C1 to attachment1’s CFrame.

weld.Part0 = handle
weld.Part1 = bodyPart

weld.C0 = attachment0.CFrame
weld.C1 = attachment1.CFrame

Parent the Weld to the Handle.

weld.Parent = handle

Now, the next lines are part of the calculation aspect.
Create a variable that stores the difference of the body part’s Position and the Handle’s, and do the same for the Orientation properties.

local position = handle.Position - bodyPart.Position
local rotation = handle.Orientation - bodyPart.Orientation

Define two more variables: one that stores the product of body part’s CFrame and position converted to a CFrame; the other will store rotation converted to a rotated CFrame.

local cframe = bodyPart.CFrame * CFrame.new(position)

local roX, roY, roZ  = rotation.X, rotation.Y, rotation.Z
local rad = math.rad
-- You may be able to use CFrame.fromEulerAnglesXYZ instead.
local angles = CFrame.Angles(rad(roX), rad(roY), rad(roZ))

All you have to do now is set the Handle’s CFrame to cframe * angles, and apply the accessory.

handle.CFrame = cframe * angles

-- You can just parent the accessory to the character, too.
-- accessory.Parent = character.Humanoid
character.Humanoid:AddAccessory(accessory)
1 Like

@Ovibion is right, on client side AddAccessory() is not welding the accessories, thats intended according to a Roblox Staff which provided a simple code to re-weld them, just call
addAccoutrement(Character, Accessory) everytime you want to add a client accessory, make sure you deleted the Welds before using it.

function weldAttachments(attach1, attach2)
	local weld = Instance.new("Weld")
	weld.Part0 = attach1.Parent
	weld.Part1 = attach2.Parent
	weld.C0 = attach1.CFrame
	weld.C1 = attach2.CFrame
	weld.Parent = attach1.Parent
	return weld
end

local function buildWeld(weldName, parent, part0, part1, c0, c1)
	local weld = Instance.new("Weld")
	weld.Name = weldName
	weld.Part0 = part0
	weld.Part1 = part1
	weld.C0 = c0
	weld.C1 = c1
	weld.Parent = parent
	return weld
end

local function findFirstMatchingAttachment(model, name)
	for _, child in pairs(model:GetChildren()) do
		if child:IsA("Attachment") and child.Name == name then
			return child
		elseif not child:IsA("Accoutrement") and not child:IsA("Tool") then -- Don't look in hats or tools in the character
			local foundAttachment = findFirstMatchingAttachment(child, name)
			if foundAttachment then
				return foundAttachment
			end
		end
	end
end

function addAccoutrement(character, accoutrement)  
	accoutrement.Parent = character
	local handle = accoutrement:FindFirstChild("Handle")
	if handle then
		local accoutrementAttachment = handle:FindFirstChildOfClass("Attachment")
		if accoutrementAttachment then
			local characterAttachment = findFirstMatchingAttachment(character, accoutrementAttachment.Name)
			if characterAttachment then
				weldAttachments(characterAttachment, accoutrementAttachment)
			end
		else
			local head = character:FindFirstChild("Head")
			if head then
				local attachmentCFrame = CFrame.new(0, 0.5, 0)
				local hatCFrame = accoutrement.AttachmentPoint
				buildWeld("HeadWeld", head, head, handle, attachmentCFrame, hatCFrame)
			end
		end
	end
end

-----------------------------------------------------------

	for _, acc in pairs(plr.Character.Humanoid:GetAccessories()) do
		local newAcc = acc:Clone()
		local weld = newAcc:FindFirstChildWhichIsA("Weld", true)
		if weld then
			weld:Destroy()	
		end
		addAccoutrement(YourDummy, newAcc)
	end

2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.