How to bind part to bone?

How can I bind a part/mesh to a bone?

I have a skinned mesh character in my game. I want it to be able to hold objects, but you can’t weld bones in Roblox. How can I make a baseball bat bind to my player’s hand like he is holding it?

I have tried looking around for answers but haven’t found any working ones. I tried using a script to make the baseball bat’s position the same as the bone’s transformedworldcframe but that has a huge delay.
I also of course tried making it as a tool, but it doesn’t work as the player is skinned mesh, not r6 or r15.

You can weld the mesh, and there are two methods of doing so.

Welding Directly
This is a much more efficent method because you only have to update it once.

local root_part; --//Part you want to attach
local mesh_part; --//Meshpart bind to mesh

local heartbeat = game:GetService('RunService').Heartbeat;
local weld = Instance.new('Weld') do --//"Do" is for organization
    weld.Part0 = root_part;
    weld.Part1 = mesh_part;
    weld.C0 = root_part.CFrame:Inverse() * mesh_part.CFrame;
end

Welding to the Bone
Welding to the bone requires an event(Heartbeat) which updates every 1/40 second, this is due to the “WorldPosition” property of the bone not detectable through “:GetPropertyChangedSignal(‘WorldPosition’)”. Roblox decided to remove the part position events when reacting to physics because of the amount of updates it uses, which would slow down the physics engine.

local root_part; --//Any part attached to the character (RootPart reccomended)
local mesh_part; --//Part you want to attach
local bone; --//Bone you want it to weld to

local heartbeat = game:GetService('RunService').Heartbeat;
local weld = Instance.new('Weld') do --//"Do" is for organization
    weld.Part0 = root_part;
    weld.Part1 = mesh_part;
end

heartbeat:Connect(function(time)
    --//Runs 40 times a second
    
    weld.C0 = root_part.CFrame:Inverse() * CFrame.new(bone.WorldPosition);
end);

What is Heartbeat?
Heartbeat is an event which fires about 40 times every second, and gives you the exact time it took (should be a number around 1/40) in the parameters: “function(time)”

Using “taks.wait()” instead of "wait()"
Using task.wait() uses the heartbeat event, which waits around 1/40 seconds, and returns the exact time it took. Using task.wait() is faster than using wait() because wait() waits only 1/20 seconds.

3 Likes

Thank you for answering.
It doesn’t seem to work - I get the error ’ Expected BasePart got Bone for Weld:Part1’

local root_part = script.Parent.Parent.Torso

local bone = root_part:FindFirstChild("mixamorig:Hips"):FindFirstChild("mixamorig:Spine"):FindFirstChild("mixamorig:Spine1"):FindFirstChild("mixamorig:Spine2"):FindFirstChild("mixamorig:RightShoulder"):FindFirstChild("mixamorig:RightArm"):FindFirstChild("mixamorig:RightForeArm"):FindFirstChild("mixamorig:RightHand")

local heartbeat = game:GetService('RunService').Heartbeat;
local weld = Instance.new('Weld') do
	weld.Part0 = root_part; 
	weld.Part1 = bone;
end

heartbeat:Connect(function(time)
	weld.C0 = root_part.CFrame:Inverse() * CFrame.new(bone.WorldPosition);
end);

Welds simply don’t seem to allow bones. Any help is appreciated

Whoops, I made a mistake in the code, I fixed it :smiley:

My bad I should’ve noticed that the mesh part wasn’t included in the script haha
Thanks! The weld works really well!

1 Like