Returning Motor6ds used in Animationtrack

Is there a method to get all the motor6ds used in an animation track?

3 Likes

I have found a way to find out if a motor6d is currently being used in any animation but it doesn’t specify it. I need a better way to find out if the motor is being used in an animation while knowing which animation it is.

1 Like

Here is a function that can generate an array of Motor6Ds used in an Animation using its AnimationId and a rig model:

local animation_clip_provider = game:GetService("AnimationClipProvider")

local function get_motor6ds_in_animation(animation_id, rig_model)
	--First, request the KeyframeSequence from ROBLOX.
	--This is a network call, so it will yield and needs to be wrapped in pcall.
	
	local success, keyframe_sequence = pcall(animation_clip_provider.GetAnimationClipAsync, animation_clip_provider, animation_id)
	if not success then
		warn("Unable to get Motor6D used in animation \"" .. animation_id .. "\" for reason: " .. tostring(keyframe_sequence))
		return nil
	end
	
	--Next, find all of the BaseParts and Motor6Ds in the rig.
	
	local motor6d_lookup = {}	--{[Part0] : {[Part1] : Motor6D}}
	local part_lookup = {}		--{[Name] : BasePart}
	
	for _, object in ipairs(rig_model:GetDescendants()) do
		if object:IsA("BasePart") then
			part_lookup[object.Name] = object
		elseif object:IsA("Motor6D") then
			local part0_table = motor6d_lookup[object.Part0]
			if not part0_table then
				part0_table = {}
				motor6d_lookup[object.Part0] = part0_table
			end
			part0_table[object.Part1] = object
		end
	end
	
	--Iterate through all of the Keyframes of the KeyframeSequence. Each one contains a tree of poses that identify
	--which Motor6Ds they require to perform the animation. Only Motor6Ds present in your rig will be able to be identified.
	
	local used_motor6ds = {}
		
	for _, keyframe in ipairs(keyframe_sequence:GetChildren()) do
		if keyframe:IsA("Keyframe") then
			local root_stack = keyframe:GetChildren()
			
			while #root_stack > 0 do
				local root = root_stack[#root_stack]
				table.remove(root_stack)
				
				local part0 = part_lookup[root.Name]
				
				local poses = root:GetChildren()
				table.move(poses, 1, #poses, #root_stack + 1, root_stack)
				
				if part0 then
					local motor6ds = motor6d_lookup[part0]
					if motor6ds then
						for _, pose in ipairs(poses) do
							local motor6d = motor6ds[part_lookup[pose.Name]]
							if motor6d then
								used_motor6ds[motor6d] = true
							end
						end
					end
				end
			end
		end
	end
	
	--Lastly, move the used Motor6Ds from a lookup into an array. If you'd prefer the lookup, then just return that.
	
	local index = 0
	local motor6d_array = {}
	
	for motor6d in pairs(used_motor6ds) do
		index += 1
		motor6d_array[index] = motor6d
	end
	
	return motor6d_array
end

The success of this method is, however, ultimately dependent on being provided a compatible rig. The raw animation data can be fetched from ROBLOX via AnimationClipProvider:GetAnimationClipAsync(), but the returned raw data only references things by name; you have to use those names to find the Motor6Ds yourself. If the rig is incompatible with the loaded animation, some or all of the Motor6Ds used may be missing from the returned array.

2 Likes

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