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)