Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
3

Why does the Joint Snap back to One axis?

Asked by 9 years ago

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.

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. nighttimeninja314 120 — 9y
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. Spongocardo 1991 — 9y
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. Spongocardo 1991 — 9y
0
Nope didn't work :/ nighttimeninja314 120 — 9y

1 answer

Log in to vote
1
Answered by
BlueTaslem 18071 Moderation Voter Administrator Community Moderator Super Administrator
9 years ago

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".

Ad

Answer this question