Moving Part Along Z Axis

Hello everyone! I have a quick question regarding the CFrame and Vectors of what I’m trying to accomplish here. I’m working on a weapon attachment modification system where you can move the attachment along the Z axis of a rail. I got it down… Mostly…

I’m not the best with math and vectors so I’m asking for help on how to correct the attachment moving relative to where the mouse is hitting the rail. I’ll provide a gif of what I’m talking about below, but when it’s facing one direction, the attachment moves perfectly with the X Movement of the mouse; however, rotate the gun 180 degrees and then it starts moving in the opposite direction the mouse is moving. Just gotta learn how to fix this so help is much appreciated!

Also, side-note, if you could help me stop it from doing that stupid little drop when you first grab it, that would be amazing.

Media Below:
https://gyazo.com/ecd45a8fd10e5594b836f44e12b6c475

Here’s the code:

if modding and modTarget and modSlider then
	if elements.MouseHeld and modTarget then
		if modSlider then
			local Size = modSlider.Size

			local Offset = CFrame.new(0, 0, Size.Z / 2)
			local Direction = modSlider.CFrame.LookVector
			local LineRay = Ray.new((modSlider.CFrame * Offset).Position, Direction)

			local closestPoint = LineRay:ClosestPoint(mouse.Hit.Position)
			local minBound = modSlider.Position - modSlider.Size / 2
			local maxBound = modSlider.Position + modSlider.Size / 2

			local newZ = math.clamp(closestPoint.Z, minBound.Z, maxBound.Z)
			local newCFrame = modSlider.CFrame:ToWorldSpace(CFrame.new(0, 0, newZ - modSlider.Position.Z)) * modTarget.PrimaryPart.CFrame:ToObjectSpace(modTarget.PrimaryPart.CFrame)
			modTarget:SetPrimaryPartCFrame(newCFrame)
		end
	end
end;

1 Like

Try checking the orientation of the gun and when it’s in the opposite then do the opposite thing? Not sure if it works

1 Like

Doesn’t really work out all that well because it can be several different orientations all that affect the direction. I just need to learn how to use object space better I guess. Nobody has been replying and this is the second time I post so I’m assuming not many people know either.

3 Likes

Have you tried looking on the Internet or for tutorials? I’m not sure, but I know a person that may be able to help you (he’s very good w it codes) it’s @DasKairo

1 Like

Bruh.

1 Like

Are you able to help @TridentXR? You were the only person that came to my mind

:rofl::rofl::rofl:

1 Like

Also another way is having it locked on certain Orientations so taht you a able to solve the problem?

1 Like

It shouldn’t be locked to certain orientations. Just gotta find a way to get it to work properly.

From your code snippet, it looks like you’re using a slider to move the attachment along the Z-axis of a rail, and you’re using a ray to detect the position of the mouse cursor on the rail.

To fix the issue where the attachment moves in the opposite direction of the mouse cursor when the gun is rotated 180 degrees, you’ll need to take into account the orientation of the rail relative to the world axes. One way to do this is to use the rail’s CFrame to transform the ray into the rail’s local space, and then use the transformed ray to compute the closest point on the rail to the mouse cursor.

Here’s an updated version of your code that takes this into account:

if modding and modTarget and modSlider then
	if elements.MouseHeld and modTarget then
		if modSlider then
			local Size = modSlider.Size

			local Offset = CFrame.new(0, 0, Size.Z / 2)
			local Direction = modSlider.CFrame.LookVector
			local LineRay = Ray.new((modSlider.CFrame * Offset).Position, Direction)

			-- transform the mouse cursor position into the rail's local space
			local localMousePos = modSlider.CFrame:Inverse() * mouse.Hit.Position

			-- compute the closest point on the rail to the transformed mouse cursor
			local closestPoint = Vector3.new(localMousePos.X, localMousePos.Y, 0)
			closestPoint = modSlider.CFrame * closestPoint

			local minBound = modSlider.Position - modSlider.Size / 2
			local maxBound = modSlider.Position + modSlider.Size / 2

			local newZ = math.clamp(closestPoint.Z, minBound.Z, maxBound.Z)
			local newCFrame = modSlider.CFrame:ToWorldSpace(CFrame.new(0, 0, newZ - modSlider.Position.Z)) * modTarget.PrimaryPart.CFrame:ToObjectSpace(modTarget.PrimaryPart.CFrame)
			modTarget:SetPrimaryPartCFrame(newCFrame)
		end
	end
end;

Regarding the issue with the attachment dropping when you first grab it, it’s hard to say without seeing more of your code. One possibility is that the attachment’s position is not being set correctly when it’s first grabbed. One solution is to set the attachment’s position to the closest point on the rail to the attachment’s current position when it’s first grabbed. This should ensure that the attachment starts at the correct position on the rail.

This is doing some real crazy stuff now. It doesn’t follow the mouse, and I’m not entirely sure how to fix it. The following code is the closest I could get, but it’s jittering around all over the place and not moving in sync with the mouse:

Here’s the code and media:

if modding and modTarget and modSlider then
	if elements.MouseHeld and modTarget then
		if modSlider then
			local Size = modSlider.Size

			local Offset = CFrame.new(0, 0, Size.Z / 2)
			local Direction = modSlider.CFrame.LookVector
			local LineRay = Ray.new((modSlider.CFrame * Offset).Position, Direction)

			local localMousePos = modSlider.CFrame:Inverse() * mouse.Hit.Position
			local closestPoint = Vector3.new(0, 0, localMousePos.Z)
			local minBound = modSlider.Position - modSlider.Size / 2
			local maxBound = modSlider.Position + modSlider.Size / 2

			local newZ = math.clamp(closestPoint.Z, minBound.Z, maxBound.Z)
			local newCFrame = modSlider.CFrame:ToWorldSpace(CFrame.new(0, 0, newZ - modSlider.Position.Z)) * modTarget.PrimaryPart.CFrame:ToObjectSpace(modTarget.PrimaryPart.CFrame)
			modTarget:SetPrimaryPartCFrame(newCFrame)
		end
	end
end;

I do see a couple of potential areas that could be causing problems:

  • closestPoint is being calculated as Vector3.new(0, 0, localMousePos.Z) . This means that closestPoint is always going to have an x and y value of 0, which could be causing the jittery movement. You might want to try calculating closestPoint as Vector3.new(localMousePos.X, localMousePos.Y, localMousePos.Z) instead.

  • The line where newCFrame is being calculated is a bit confusing. It’s multiplying modSlider.CFrame:ToWorldSpace(CFrame.new(0, 0, newZ - modSlider.Position.Z)) by modTarget.PrimaryPart.CFrame:ToObjectSpace(modTarget.PrimaryPart.CFrame) . It’s possible that this calculation is causing the jittery movement. You might want to try simplifying this calculation to just modSlider.CFrame:ToWorldSpace(CFrame.new(0, 0, newZ - modSlider.Position.Z)) and see if that helps.

Again, without more context it’s difficult to say for sure what’s causing the issue. You might want to try debugging the code by printing out the values of different variables (e.g. localMousePos , closestPoint , newCFrame ) to see if you can identify any patterns or issues.

Would you be willing to chat on discord and work this out with me? That is all the code that relates to this at all, but regardless, if there is a better way of doing this, like you said with local mouse position, I would love to learn how because I don’t understand vectors enough to pull it off myself.

Also the example you provided, with the localMousePos XYZ included was causing wacky behavior that would yanking it around as well.

I can’t right now, as I’m a bit busy, I just hop on here every once in a while to help out. I had to look up some stuff myself for this, which is why the solution wasn’t exactly clear. I do know another scripter that knows a bit more Cframes and vectors. DM Wake#9850 on Discord / @WakeTheTyrant

Thank you very much for your help. It’s gotten me further than I was able to myself! I’ll reach out to him now.

No problem, hope it works out.

Me too, this crap is a plague.

1 Like