Hello everyone,
Not sure how to explain this issue, but here goes.
So I’ve been experimenting with Drag Detectors recently, and they’re a great addition in my opinion! There’s just one problem - they only work in Studio as the devs work out any bugs they still have before release. Therefore, I’ve been trying to find an alternative to Drag Detectors, and I found this post by lilsquish08. All credits go to them.
Local Script, in StarterPlayerScripts
local UserInputService = game:GetService("UserInputService")
local TAG_NAME = "Grabbable"
local player = game.Players.LocalPlayer
local mouse = player:GetMouse()
local character = player.Character or player.CharacterAdded:Wait()
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
local head = character:WaitForChild("Head")
local requestGrab = game.ReplicatedStorage.RequestGrab
local stopGrab = game.ReplicatedStorage.StopGrab
local trackingPart = nil
local heartbeat
local grabDistance = 100
function UpdateTrackingPart ()
local position = head.Position + (mouse.Hit.Position - head.Position).Unit * 6
trackingPart.BodyPosition.Position = position
end
function MouseDown ()
local target = mouse.Target
if target then
local distanceFromTarget = (humanoidRootPart.Position - target.Position).Magnitude
if distanceFromTarget < grabDistance then
if target and requestGrab:InvokeServer(target) then
trackingPart = target
heartbeat = game:GetService("RunService").Heartbeat:Connect(UpdateTrackingPart)
print("Player started grabbing")
end
end
end
end
function MouseUp ()
if not trackingPart then return end
stopGrab:FireServer(trackingPart)
trackingPart = nil
heartbeat:Disconnect()
print("Player stopped grabbing")
end
function CharacterAdded (character)
mouse.TargetFilter = character
end
UserInputService.InputBegan:Connect(function(inputObject, processed)
if processed then return end
if inputObject.UserInputType == Enum.UserInputType.MouseButton1 then
MouseDown()
end
end)
UserInputService.InputEnded:Connect(function(inputObject, processed)
if processed then return end
if inputObject.UserInputType == Enum.UserInputType.MouseButton1 then
MouseUp()
end
end)
CharacterAdded(player.Character or player.CharacterAdded:Wait())
player.CharacterAdded:Connect(CharacterAdded)
Server Script, in ServerScriptService
local TAG_NAME = "Grabbable"
local collectionService = game:GetService("CollectionService")
local parts = collectionService:GetTagged(TAG_NAME)
local playerParts = {}
function RequestGrab (player, part)
if playerParts[player] then return false end
if not collectionService:HasTag(part, TAG_NAME) then
return false
end
local bp = Instance.new("BodyPosition")
local bg = Instance.new("BodyGyro")
bp.MaxForce = Vector3.new(math.huge, math.huge, math.huge)
bp.D = 900
bp.Position = part.Position
bp.Parent = part
bg.MaxTorque = Vector3.new(math.huge, math.huge, math.huge)
bg.CFrame = part.CFrame
bg.Parent = part
part:SetNetworkOwner(player)
playerParts[player] = part
return true
end
function StopGrab (player, part)
if playerParts[player] ~= part then return false end
part.BodyPosition:Destroy()
part.BodyGyro:Destroy()
playerParts[player] = nil
end
game.ReplicatedStorage.RequestGrab.OnServerInvoke = RequestGrab
game.ReplicatedStorage.StopGrab.OnServerEvent:Connect(StopGrab)
game.Players.PlayerRemoving:Connect(function(player)
if playerParts[player] then
StopGrab(player, playerParts[player])
end
end)
There is a RemoteFunction “RequestGrab” and a RemoteEvent “StopGrab” in ReplicatedStorage if you are looking to recreate this.
The issues that I’m having with this: one, the model is able to go in the air. I need movement to be clamped along the XZ plane. Is there any way to do this?
Secondly, I also want the model to be able to turn. The optimal solution, in my opinion, is to apply the force at the location of the part instead of at the model’s center of mass, like on Drag Detectors when you have ApplyAtCenterOfMass
unchecked. This also works if the player can rotate the model with a key.
If anyone has any knowledge on either problem, any help is appreciated. Thanks in advance!