Help making part rotate when using drag detectors (strange behaviour)

So I am trying to create a system where you can pick up objetcs using drag detectors, and then rotate then using R. The dragging works fine, however the rotation is very strange.

I am using the Scriptable drag detctor style, and context action service to check when R is pressed, and then passing that to a HandleRotation function. This function sets self.rotation to self.rotation + 2 (Vector3) in a RenderStepped, and this rotation is used in the function that calculates where to place the object.

However, DragDetector:SetDragStyleFunction() only fires when then player moves the mouse, so if their mouse is still and they hold R, the rotation is not updated until the move their mouse.

I have tried setting the DragFrame and the object’s CFrame to the new rotation in the HandleRotation function, and while it works WHILE the player is holding R, as soon as they let go it reverts back to the original rotation.
However, once they move their mouse after holding R, the object then majically rotates to where it was before.

This behaviour is very odd, and I’m wondering if it’s a bug or if I’m just stupid.
Here is a video of the problem:

The useful parts of my code:

function Draggable:getNewFrameGivenRayFromPlayer(rayFromPlayer)
	local rayToShoot = Ray.new(rayFromPlayer.Origin, rayFromPlayer.Direction.Unit * self.CARRY_DISTANCE)
	local player = game.Players.LocalPlayer
	local blockcastResult = self:getBlockcastAvoidingCharacter(rayToShoot, player.character)
	-- if we don't hit anything closer than CARRY_DISTANCE, we'll place it CARRY_DISTANCE ahead of us.
	local finalDistance = self.CARRY_DISTANCE
	if blockcastResult then
		finalDistance = blockcastResult.Distance
		if self:isPhysicalDrag() then
			-- this will attempt to place it slightly beyond the surface.
			-- in the physical case, this helps push/slide along walls. (We don't to this in the geometric case or we'd penetrate the other objects)
			finalDistance = finalDistance + 0.2
		end
	end	
	local finalPosition = rayFromPlayer.Origin + rayFromPlayer.Direction.Unit * 17
	return self.rotation + finalPosition
end

function Draggable:HandleRotation(actionName, state)
	if actionName ~= "Rotate" then return end
	if state == Enum.UserInputState.Begin then
		self._inputTrove:BindToRenderStep("ObjectRotation", Enum.RenderPriority.Last.Value, function()
			self.rotation = self.rotation * CFrame.fromEulerAnglesXYZ(self.rotation.X, self.rotation.Y + math.rad(2), self.rotation.Z)
			--if self.DragDetector.
			self.DragDetector.DragFrame = self:getDesiredNewWorldCFrame(self.oldCursorRay)
			self.Instance:PivotTo(self.DragDetector.DragFrame)
			--self.DragDetector:RestartDrag()
		end)
	elseif state == Enum.UserInputState.End then
		--self.DragDetector:RestartDrag()
		self._inputTrove:Destroy()
	end
end

self._trove:Connect(self.DragDetector.DragStart, function(player, ray, viewFrame, hitFrame, clickedPart)
		if clickedPart ~= self.Instance then return false end
		self.rotation = CFrame.fromEulerAnglesXYZ(math.rad(clickedPart.Rotation.X), math.rad(clickedPart.Rotation.Y), math.rad(clickedPart.Rotation.Z))
		Net:RemoteEvent("RequestNetworkOwnership"):FireServer(clickedPart, true)

		self._inputTrove = self._trove:Extend()
		ContextActionService:BindAction("Rotate", function(action, state)
			self:HandleRotation(action, state)
		end, true, Enum.KeyCode.R)
end)

self.DragDetector:SetDragStyleFunction(function(cursorRay)
		self.oldCursorRay = cursorRay
		local new = self:getDesiredNewWorldCFrame(cursorRay)
    return new
end)
1 Like

Did you find solution, am experiencing that too

Sadly not, I think an entirely custom DragDetector implementation may be needed in order to achive that effect

1 Like