I gave SetDragStyleFunction a whirl tonight and ran into a few issues. Let me explain what I was trying to use it for first. I tried to use it to position a draggable object in front of the character at all times. The script positioned the object in front of the character’s head if the player was in third person. If the player was in first person, the object would be positioned wherever their mouse is on the viewport. In most circumstances, that’d be in the center of the screen. Here’s what the script looked like:
local DISTANCE_FROM_CHARACTER = 4
local dragDetector = script.Parent
local draggablePart = dragDetector.Parent
local currentCamera = workspace.CurrentCamera
local currentGuiInset = game:GetService("GuiService"):GetGuiInset()
local function shouldUseHeadAsOrigin(): (boolean, CFrame?)
local cameraSubject = currentCamera.CameraSubject
if cameraSubject then
local isLockedToHead = cameraSubject:IsA("Humanoid")
if not isLockedToHead then
return false
end
local currentHead = cameraSubject.Parent:FindFirstChild("Head")
if currentHead==nil then
return false
end
local currentCameraFocusPosition = currentCamera.Focus.Position
local currentCameraPosition = currentCamera.CFrame.Position
local isCameraInFirstPerson = (currentCameraFocusPosition-currentCameraPosition).Magnitude < 0.75
if not isCameraInFirstPerson then
return true, currentHead.CFrame
end
end
return false
end
dragDetector:SetDragStyleFunction(function()
local shouldUseHead, headCFrame = shouldUseHeadAsOrigin()
if shouldUseHead then
return CFrame.new(headCFrame.Position + headCFrame.LookVector * DISTANCE_FROM_CHARACTER) * headCFrame.Rotation
end
local currentMouseLocation = game:GetService("UserInputService"):GetMouseLocation() - currentGuiInset
local viewportCursorRay = currentCamera:ViewportPointToRay(currentMouseLocation.X, currentMouseLocation.Y)
return CFrame.new(viewportCursorRay.Origin + viewportCursorRay.Direction * DISTANCE_FROM_CHARACTER) * currentCamera.CFrame.Rotation
end)
All the DragDetectors in this post use RunLocally.
Mysterious DragStyleFunction Parameter
The first issue I ran into was that I had no clue what parameters were passed to the DragStyleFunction from the docs and from studio’s intellisense. The only hint that it passed down a parameter was this part from the documentation:
it receives the signal’s world space cursor ray
Which in itself is a bit vague. It mentions the cursor, but from what I saw, it’s not the same as what I did with my DragStyleFunction for the viewportCursorRay variable. It’d be nice if there was a small explanation of what the parameter really is. In addition, a simple example function that could be passed to SetDragStyleFunction on the doc site that shows off that parameter would be handy as well.
Missing AlignOrientation for Scriptable DragStyle
I was messing around with the draggable object that used the code above and I noticed that the orientation of the object didn’t match what I was giving through my DragStyleFunction. I was heavily confused because the docs said this about the CFrame that the function returns:
it returns a CFrame containing the desired location and orientation of the pivot in world space
After a bit of investigating, apparently no AlignOrientation object is created when using a Scriptable DragStyle plus the Physical ResponseStyle. The Geometric ResponseStyle works as expected, so this definitely looks to be unintentional. Here’s what it looks like:
As you can see, the part with the Geometric ResponseStyle always has the red face pointing towards the character, like it’s supposed to. However, with the one that has the ResponseStyle set to Physical, it doesn’t do anything with the orientation.
Stuttering with Geometric Dragging in First Person
When dragging an object with the ResponseStyle set to Geometric, the object stutters since it’s being CFramed after the frame has been rendered, leading the object to being always a frame behind position wise. With this ReponseStyle, I don’t think this should be happening. Here’s a quick look at that:
Unexpected Positioning
When using the Geometric ResponseStyle, the object is positioned at the CFrame I returned with my DragStyleFunction (as seen in the video above), like I expected. However, when using the Physical ResponseStyle, the object rarely seems to be positioned correctly, if ever. I’m not sure what exactly is going on here. Here’s what that looks like:
In that video, I would expect the starting drag point to be where the cursor is. At the end though, you can see the cursor be on the opposite side of the part where the drag originated. No clue if that makes sense. The DragStyle being used here is the same as earlier (scriptable with the snippet at the top).
The DragDetector does indeed have ApplyAtCenterOfMass enabled in that video. However, with or without it enabled, I still get unexpected results with where the object is ending up.
Constraints Remaining after Dying
If a player is dragging a DragDetector when their character respawns, the AlignPosition and AlignOrientation constraints aren’t cleaned up until a different player tries dragging the object. There’s also some kind of desync when the ResponseStyle is Geometric (the client has it frozen but the server doesn’t).
This means if a player dies while falling and dragging an object, the object has the potential to be stuck floating in the air and out of reach.