So I am trying to make a part that can be moved in game by the movement handles. It is working fine, but when I use ArcHandles to rotate the part and then again try moving it, it moves in the wrong direction.
I think the script is using world axis to move the part.
How can I make it so that it uses the object’s axis?
Here is the script:
local handle = script.Parent
local Increment = handle.Adornee.ResizeIncrement
local CF
handle.MouseButton1Down:Connect(function()
CF = handle.Adornee.CFrame
end)
handle.MouseDrag:Connect(function(id,distance)
handle.Adornee.CFrame = CF + (Vector3.FromNormalId(id) * (math.floor(distance / Increment) * Increment))
end)
Any help is appreciated!
1 Like
You’ll have to transfer world coords into local coords and then back into world coords.
Do all your fancy movement things in the local coords and transfer it to world coords.
Use
local nCFrame = handle.Adornee.CFrame:ToObjectSpace()
local nCFrame = handle.Adornee.CFrame:ToWorldSpace()
Although I don’t understand why it needs a cframe, why can’t it just use Vector3?
Or unless it can and I just don’t know…
API Reference Here
1 Like
How can I implement that in my script?
1 Like
Well, I’m not familiar with ArcHandles. What I can help you with is that from what I can see in your script is that you’ll want to:
- Convert the CF variable into a local space CFrame (Could be redundant)
- You’ll need to make the Vector3.FromNormalID() a CFrame to also convert into local space
1 Remember that converting needs a reference to an object so make sure that object is the handle [Hence: handle.Adornee.CFrame:ToWorldSpace()]
2 You’re using the adornee’s cframe as reference
- Do the movement mojo
- Then Reconvert this new CFrame to World Space using the adornee as reference again.
- Set the CFrame and you “should” be good.
Don’t worry, if that doesn’t solve your problem I might have another, albeit hacky, solution ready. And what’s the worse that could happen, you just used some complex CFrame function.
1 Like
How can I convert Vector3.FromNormalId into a CFrame?
1 Like
Simply do:
local badboi = CFrame.new(Vector3.FromNormalId())
I highly recommend you read the CFrame API page and do some research on youtube on how to use it if you haven’t already, as it is one of the most important parts of physics.
1 Like
When I try to multiply it by the “math.floor” thing it gives me an error:
Here is the line which gives the error:
local bad = CFrame.new(Vector3.FromNormalId(id)):ToObjectSpace()
local bad2 = bad * math.floor(distance/Increment) * Increment
At the second line it give me error:
[Players.StrategicPlayZ.PlayerGui.Handles.MoveHandles:12: bad argument #2 to ‘?’ (Vector3 expected, got number)
How to fix this?
You are not converting to object space correctly.
To convert to object space correctly you need an object to take the origin position (0,0,0) and you would get a new Vector3 for the CFrame you are wishing to convert relative to the object.
Also, a CFrame is not a Vector3, its a combination of both a Position and an Angle. Separate the Vector3 from the CFrame by doing CFrame.Position
The code you need is:
local bad = handle.Adornee.CFrame:ToObjectSpace(CFrame.new(Vector3.FromNormalId(id)))
local bad2 = bad.Position * math.floor(distance/Increment) * Increment
local bad3 = handle.Adornee.CFrame:ToWorldSpace(CFrame.new(bad2)).Position
Now correct me if I’m wrong, but this converts the Vector into object space, does the fancy mojo, and the converts it back into world space while giving you the new position. Not sure if this will work, but you gotta try it.
This is how it look like in my script. It doesn’t seem to work. The part just teleports somewhere far away when I try to drag it:
local handle = script.Parent
local Increment = handle.Adornee.ResizeIncrement
local CF
handle.MouseButton1Down:Connect(function()
CF = handle.Adornee.CFrame
end)
handle.MouseDrag:Connect(function(id,distance)
local bad = handle.Adornee.CFrame:ToObjectSpace(CFrame.new(Vector3.FromNormalId(id)))
local bad2 = bad.Position * math.floor(distance/Increment) * Increment
local bad3 = handle.Adornee.CFrame:ToWorldSpace(CFrame.new(bad2)).Position
local nFrame = CF + bad3
handle.Adornee.CFrame = nFrame
end)
Try changing nFrame to
local nFrame = handle.Adornee.CFrame:ToWorldSpace(handle.Adornee.CFrame:ToObjectSpace(CF) + bad2)
It still doesn’t work. The part still teleport to random position.
Can you show me what is happening or at least provide me the game link so I can test it out myself? I don’t know exactly what’s going on.
So this code sends it flying.
And the original issue is that when you rotate the block and try to move it, the part doesnt use its local axis. Correct?
Yes.
(Just to increase the characters to be able to post this. Ignore this whole line)
Alright, can you show me how the original code behaved through a video?
The issue may be due to you getting a vector3 axis using the id.
Yes, but that doesn’t highlight your issue. Can you rotate the block with arc handles and then show me what happens when you move it?
Okay, I now understand your issue much better.
We don’t need to convert them to world and object space but rather we need to get the Look/Up/Right Vectors
With the help of the API on Arc Handles here is what you need:
handle.MouseDrag:Connect(function(id, distance)
local moving = handle.Adornee
local axi = {
[Enum.NormalId.Right] = moving.CFrame.RightVector,
[Enum.NormalId.Left] = -moving.CFrame.RightVector,
[Enum.NormalId.Top] = moving.CFrame.UpVector,
[Enum.NormalId.Bottom] = -moving.CFrame.UpVector,
[Enum.NormalId.Front] = moving.CFrame.LookVector,
[Enum.NormalId.Back] = -moving.CFrame.LookVector,
}
moving.CFrame = CF + axi[id] * (math.floor(distance / Increment) * Increment)
end)
Yeah, I didn’t want to have to use if statements so much so this is what I made.
2 Likes