Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

Why does the Joint Snap back to One axis?

In this code I wrote, I created a tool that allows me to edit the joints of a specific object with ArcHandles. When I move it on one axis, it works fine and accurately. However, when I try to move it on another axis, it pretty much reverts the joint back to Its original position and begins to move along the new axis. I don't want it to snap back to the old angle. This code is a little more advanced, So I highly appreciate any help given.

To see this in action, you can go here : Hand Test

wait(1)	
	local mouse = game.Players.LocalPlayer:GetMouse()
	local player = game.Players.LocalPlayer
	local character = player.Character
	local arc = script.Parent.Parent.Arc -- arc handles. 
local obj = nil
local current = nil
local Angle = nil

function checkfor(part1) -- rather than clicking the joint parts, i can click one of the parts and find its source. No problem here, just explaining
local m = workspace.Model:GetChildren() -- the model I am animating
for i = 1, #m do
	if m[i]:FindFirstChild("Motor6D") then
		 if m[i].Motor6D.Part1 == part1 then
		return m[i]
	end
end
end
end
mouse.Button1Down:connect(function() -- around here is where it gets a bit iffy
	if mouse.Target and checkfor(mouse.Target) then
		script.Parent.Coo.Value = mouse.Target
		obj = checkfor(mouse.Target)
	arc.Adornee = obj
	arc.MouseButton1Down:connect(function()
		local x,y,z = obj.Motor6D.C0:toEulerAnglesXYZ() 
	local cf = CFrame.new(obj.Motor6D.C0.p)
	arc.MouseDrag:connect(function(axis,angle,radius)
		if axis == Enum.Axis.X then -- determines which axis is being moved with the handles. Feel free to edit the below; its a possible problem spot.
		Angle = CFrame.Angles(angle,0,0)
		elseif axis == Enum.Axis.Y then
		Angle = CFrame.Angles(0,angle,0)
		elseif axis == Enum.Axis.Z then
		Angle = CFrame.Angles(0,0,angle)
		end
	obj.Motor6D.C0 =(cf) * Angle * CFrame.Angles(x,y,z) -- sets the final CFrame for the joint. This is most likely where the math and cframe issue comes from.
end)
	end)
	
	
	end
end)

Quick reminder, this code is functional, it just has a bit of some Rotational stuff errors.

4 comments

0

Why did I get a bad rating? I stated what I expected and what I got, Followed all the rules. I say this is a valid post.

0

You get that sometimes. I got a bad rating once because some guy was jealous I got an accepted answer and he didn't.

0

On the lines where you set the Angle variable, try adding x, y or z in place of the 0's. (For example: Angle = CFrame.Angles(angle,y,z)) Not too sure, so I didn't post it as an answer.

0

Nope didn't work :/

1 answer

✓ Accepted answer

First, you should fix your tabbing and spacing. It will make your code much easier to read.

wait(1) 
local mouse = game.Players.LocalPlayer:GetMouse()
local player = game.Players.LocalPlayer
local character = player.Character
local arc = script.Parent.Parent.Arc -- arc handles. 
local obj = nil
local current = nil
local Angle = nil

function checkfor(part1)
	-- rather than clicking the joint parts, i can click one of the parts
	-- and find its source. No problem here
	local m = workspace.Model:GetChildren() -- the model I am animating
	for i = 1, #m do
		if m[i]:FindFirstChild("Motor6D") then
			if m[i].Motor6D.Part1 == part1 then
				return m[i]
			end
		end
	end
end

mouse.Button1Down:connect(function()
	-- around here is where it gets a bit iffy
	if mouse.Target and checkfor(mouse.Target) then
		script.Parent.Coo.Value = mouse.Target
		obj = checkfor(mouse.Target)
		arc.Adornee = obj
		arc.MouseButton1Down:connect(function()
			local x,y,z = obj.Motor6D.C0:toEulerAnglesXYZ() 
			local cf = CFrame.new(obj.Motor6D.C0.p)
			arc.MouseDrag:connect(function(axis,angle,radius)
				if axis == Enum.Axis.X then
					-- determines which axis is being moved with the handles.
					-- Feel free to edit the below; its a possible problem spot.
					Angle = CFrame.Angles(angle,0,0)
				elseif axis == Enum.Axis.Y then
					Angle = CFrame.Angles(0,angle,0)
				elseif axis == Enum.Axis.Z then
					Angle = CFrame.Angles(0,0,angle)
				end
				obj.Motor6D.C0 = (cf) * Angle * CFrame.Angles(x,y,z)
				-- sets the final CFrame for the joint.
				-- This is most likely where the math and cframe issue comes from.
			end)
		end)
	end
end)

I see something problematic. You're connecting to the event MouseDrag each time that you MouseButton1Down. That will cause problems, since each time you click, you make another function vying for control.

The MouseDrag event uses cf and x,y,z, though, so those need to have their scope moved to outside of the MouseButton1Down event:

		...
		local x, y, z = 0, 0, 0
		local cf = CFrame.new( obj.Motro6D.C0.p )
		arc.MouseButton1Down:connect(function()
			x,y,z = obj.Motor6D.C0:toEulerAnglesXYZ() 
			cf = CFrame.new(obj.Motor6D.C0.p)
		end)
		arc.MouseDrag:connect(function(axis,angle,radius)
		...

As far as I know, this will work at least significantly more understandably. I think it's possible that the way the CFrames multiply will not be what you want, but it should no longer "snap back".

This discussion is preserved as it was. New answers, comments, and votes are closed.