X and Z axis swaped and X is flipped

I’m making an animation plugin that lets animate multiple rigs at once. But when i try to rotate limbs specifically the arms and legs the x and z axis are swapped i’ve tried fixing it but it doesn’t work. On the torso and head the x axis is flipped and the y and z axis are swapped.
Here is the function to make the rig animatable

local function RigRender(Rig : Model)
	local F = Instance.new("Folder", game.Workspace)
	F.Name = "RigParts"
	local D = Instance.new("Folder", F)
	D.Name = "Detection"
	local P = Instance.new("Folder", F)
	P.Name = "PartControllers"
	local Motors = {}
	local Oris = {}
	local Poss = {}
	for _, a in pairs(Rig:GetChildren()) do
		if a:FindFirstChildOfClass("Motor6D") then
			for v, e in pairs(a:GetChildren()) do
				if e:IsA("Motor6D") then
					local m : Motor6D
					m = e
					local i = e.Part1
					local BaseOri = m.C1.Rotation
					local BasePos = m.C1.Position
					table.insert(Motors, m)
					table.insert(Oris, BaseOri)
					table.insert(Poss, BasePos)
					local Detect = Instance.new("Part", D)
					Detect.Massless = false
					Detect.Name = i.Name
					Detect.Size = i.Size + Vector3.new(0.01,0.01,0.01)
					Detect.Transparency = 1
					local Part = Instance.new("Part", P)
					Part.Massless = true
					Part.Name = i.Name
					Part.Size = Vector3.new(0.1,0.1,0.1)
					Part.Transparency = 1
					Part.Position = i.Position + m.C1.Position
					Part.CFrame *=
m.C1.Rotation*m.Part1.CFrame.Rotation*m.C0.Rotation*m.Part0.CFrame.Rotation
					local pPos = Part.Position
					local pOri = Part.CFrame.Rotation
					wait(0.01)
					Part.Changed:Connect(function(prop)
						if prop == "Orientation" then
							m.C1 = CFrame.new(m.C1.Position)
							m.C1 *= BaseOri*(pOri*Part.CFrame.Rotation:Inverse())
						elseif prop == "Position" then
							local Ori = m.C1.Rotation
							m.C1 = CFrame.new(BasePos+(pPos-Part.Position))
							m.C1 *= Ori
						end
					end)
					local w = Instance.new("Weld", Detect)
					w.Part0 = i
					w.Part1 = Detect
				end
			end
		end
	end
	repeat wait(0.01) until not Opened
	for i = 1, #Motors do
		local a = Motors[i]
		a.C1 = CFrame.new(Poss[i])
		local BaseOri = Oris[i]
		a.C1 *= BaseOri
	end
	F:Destroy()
end

I’ve tried switch “Part” to an attachment and using RightVector UpVector and LookVector for X Y Z. But now when i move it on an axis other than y it moves in a spiral

I’ve tried world position but not the C1 is set to -60.043, -23.85, -310.587
the function which i think is causing the issues

local Func = Part.Changed:Connect(function(prop)
	local Rot = m.C1.Rotation
	m.C1 = CFrame.new((Origin-Part.WorldPosition)+pPos)
	m.C1 *= Rot
	m.C1 *= Part.CFrame.Rotation
	Part.CFrame = CFrame.new(pPos)
end)

Origin is its original world position

Hello, I will try to explain everything as clearly as I possibly can :slight_smile:. The problem you’re describing seems to be caused by a misunderstanding of the coordinate system of the Motor6D component and how the Part objects relate to it.

The rotation of a part in Roblox is based on Euler angles (using degrees) and the order of rotation is Z, Y, X. So, if your function is incorrectly attributing these axes, it will result in incorrect rotations.

Additionally, the issue with the torso and head may be related to the model orientation in Roblox. The forward direction in Roblox is -Z (negative Z), the upward direction is +Y (positive Y), and the right direction is +X (positive X). If your models aren’t oriented with this in mind, it can also cause confusion when trying to control their rotation.

Based on the code you provided, it appears you’re using CFrame and CFrame’s rotations for controlling your rig parts. A common mistake is forgetting that the CFrame’s rotation order in Roblox is different than the Euler rotation order. The CFrame uses a rotation order of Z, X, Y.

Here are some tips to fix the issues:

For the axis swapping, it seems like you’re assuming the rotation order to be X, Y, Z while manipulating CFrames directly. Make sure that you’re accounting for the Z, X, Y rotation order while using CFrames. You can use the CFrame.fromEulerAnglesXYZ method when converting from Euler angles to a CFrame, and the .toEulerAnglesXYZ method when converting from a CFrame to Euler angles to help maintain the right order.

For flipping, you could try negating the axis which is flipped.

When you’re applying the new rotations to the Motor6D, make sure to do it in the correct order.

In your script, you might need to make these changes at the point where you’re applying the new CFrame:

Part.Changed:Connect(function(prop)
	if prop == "Orientation" then
		m.C1 = CFrame.new(m.C1.Position)
		local newOri = Part.CFrame:toEulerAnglesXYZ() -- Convert the new rotation from a CFrame to Euler angles
		m.C1 *= BaseOri*CFrame.fromEulerAnglesXYZ(newOri.x, newOri.y, newOri.z) -- Use the correct rotation order when creating a new CFrame
	elseif prop == "Position" then
		local Ori = m.C1.Rotation
		m.C1 = CFrame.new(BasePos+(pPos-Part.Position))
		m.C1 *= Ori
	end
end)

Keep in mind that this is only a basic suggestion and the code might need additional adjustments based on your specific use case and the structure of your models. If the problems persist, you might need to provide additional information about how the rigs are set up and how you’re trying to animate them.

its giving this error: attempt to index number with ‘x’

Heres a summary of how the plugin SHOULD work. Click the button to open the plugin opens a gui where you can add rigs. When you add a rig to the animation it add parts 0.01 studs bigger than each of the limbs. When these parts are selected they switch the selection a “Part Controller” which detects rotation and movement and adjusts the motor6D in the character accordingly so that the user can preview the pose. Im stuck on the rotation part, movement works just fine. For testing I’m using R6 models

If i use Cframe.Rotation for parts rotation the axis are correct but it rotates backwards

I FINALLY FIXED IT!!!

local function RigRender(Rig : Model)
	local F = Instance.new("Folder", game.Workspace)
	F.Name = "RigParts"
	local D = Instance.new("Folder", F)
	D.Name = "Detection"
	local P = Instance.new("Folder", F)
	P.Name = "PartControllers"
	local Motors = {}
	local Oris = {}
	local Poss = {}
	local Funcs = {}
	for _, a in pairs(Rig:GetChildren()) do
		if a:FindFirstChildOfClass("Motor6D") then
			for v, e in pairs(a:GetChildren()) do
				if e:IsA("Motor6D") then
					local m : Motor6D
					m = e
					local i = e.Part1
					local BaseOri = m.C1.Rotation
					local BasePos = m.C1.Position
					table.insert(Motors, m)
					table.insert(Oris, BaseOri)
					table.insert(Poss, BasePos)
					local Detect = Instance.new("Part", D)
					Detect.Massless = false
					Detect.Name = i.Name
					Detect.Size = i.Size + Vector3.new(0.01,0.01,0.01)
					Detect.Transparency = 1
					local Part = Instance.new("Part", P)
					Part.Massless = true
					Part.Name = i.Name
					Part.Size = Vector3.new(0.1,0.1,0.1)
					Part.Transparency = 1
					local pOri = m.C1.Rotation
					Part.CFrame = CFrame.new(i.Position + m.C1.Position)
					Part.CFrame *= pOri
					local pPos = Part.Position
					wait(0.01)
					local Func = Part.Changed:Connect(function(prop)
						m.C1 = CFrame.new(BasePos+(pPos-Part.Position))
						m.C1 *= pOri
						m.C1 *= (pOri:Inverse()*Part.CFrame.Rotation):Inverse()
					end)
					table.insert(Funcs, Func)
					local w = Instance.new("Weld", Detect)
					w.Part0 = i
					w.Part1 = Detect
				end
			end
		end
	end
	repeat wait(0.01) until not Opened
	for i = 1, #Funcs do
		Funcs[i]:Disconnect()
	end
	for i = 1, #Motors do
		local a = Motors[i]
		a.C1 = CFrame.new(Poss[i])
		local BaseOri = Oris[i]
		a.C1 *= BaseOri
	end
	F:Destroy()
end

Turns Out It Doesn’t Fully Work I’ve Only Test Rotating and positioning individually, but if it has weird offsets

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