PcoWSkbVqDnWTu_dm2ix
We use cookies on this site to enhance your user experience
Collapse Sidebar

BuildRigFromAttachments

BuildRigFromAttachments assembles a tree of Motor6D joints for a Humanoid. Motor6D joints are required for the playback of Animation|Animations

Starting from the humanoid’s Humanoid/RootPart, the function collects all Attachments parented in the current part, whose name ends with “RigAttachment”. It then searches for a matching attachment in the character that shares the same name as the attachment. Using those two attachments, a Motor6D joint is generated based on the parts associated with the two attachments, and the Attachment/CFrames of the attachments.

See the provided code sample below to see how this function works.

Returns

Return Type Summary

Code Samples


R15 Package Importer

A script that generates an R15 character from scratch using a package’s assetId.

local PACKAGE_ASSET_ID = 193700907 -- Circuit Breaker

local AssetService = game:GetService("AssetService")
local InsertService = game:GetService("InsertService")
local MarketplaceService = game:GetService("MarketplaceService")

local function addAttachment(part,name,position,orientation)
	local attachment = Instance.new("Attachment")
	attachment.Name = name
	attachment.Parent = part
	if position then
		attachment.Position = position
	end
	if orientation then
		attachment.Orientation = orientation
	end
	return attachment
end

local function createBaseCharacter()
	local character = Instance.new("Model")

	local humanoid = Instance.new("Humanoid")
	humanoid.Parent = character
	
	local rootPart = Instance.new("Part")
	rootPart.Name = "HumanoidRootPart"
	rootPart.Size = Vector3.new(2,2,1)
	rootPart.Transparency = 1
	rootPart.Parent = character
	addAttachment(rootPart,"RootRigAttachment")
	
	local head = Instance.new("Part")
	head.Name = "Head"
	head.Size = Vector3.new(2,1,1)
	head.Parent = character
	
	local headMesh = Instance.new("SpecialMesh")
	headMesh.Scale = Vector3.new(1.25,1.25,1.25)
	headMesh.MeshType = Enum.MeshType.Head
	headMesh.Parent = head

	local face = Instance.new("Decal")
	face.Name = "face"
	face.Texture = "rbxasset://textures/face.png"
	face.Parent = head
	
	addAttachment(head,"FaceCenterAttachment")
	addAttachment(head,"FaceFrontAttachment",Vector3.new(0,0,-0.6))
	addAttachment(head,"HairAttachment",Vector3.new(0,0.6,0))
	addAttachment(head,"HatAttachment",Vector3.new(0,0.6,0))
	addAttachment(head,"NeckRigAttachment",Vector3.new(0,-0.5,0))
	
	return character,humanoid
end

local function createR15Package(packageAssetId)
	local packageAssetInfo = MarketplaceService:GetProductInfo(packageAssetId)
	
	local character,humanoid = createBaseCharacter()
	character.Name = packageAssetInfo.Name
	
	local assetIds = AssetService:GetAssetIdsForPackage(packageAssetId)
	for _,assetId in pairs(assetIds) do
		local limb = InsertService:LoadAsset(assetId)
		local r15 = limb:FindFirstChild("R15")
		if r15 then
			for _,part in pairs(r15:GetChildren()) do
				part.Parent = character
			end
		else
			for _,child in pairs(limb:GetChildren()) do
				child.Parent = character
			end
		end
	end
	
	humanoid:BuildRigFromAttachments()
	return character
end

local r15Package = createR15Package(PACKAGE_ASSET_ID)
r15Package.Parent = workspace

Lua Port of BuildRigFromAttachments

A Lua port of the Humanoid’s BuildRigFromAttachments function, so that the recursive behavior of the function can be seen.

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 i,descendant in ipairs(humanoid.Parent:GetDescendants()) do
		if descendant:IsA("BasePart") then
			table.insert(characterParts,descendant)
		end
	end
	
	buildJointsFromAttachments(rootPart,characterParts)
end