Hello! me and my friend have recently been trying to make a farming game, and the biggest problem we have encountered so far was our dragging system. essentially, were trying to code a drag detector, but rather than physically needing to drag it, it was a toggle(if you clicked, the part would continue following your first person cursor until you clicked again)
the main issue is latency. we have tried to rotate the object around the player client side, but it wont update on the server, and dropping items has a small delay before they actually drop(when we try changing the CFrame of the part when we drop, as the remote event has to communicate with the server; dependant on ping). if we try lerping the position on both the client and the server, then the lerping becomes really choppy. if we do the lerping on just the server, not only is it really choppy, but people with high ping are going to have a bad time.
currently this is what we have done(its like our third iteration)
client side
server side
as you can see, client sided i am holding an item, but on the server, the object is still in its original position.
if anyone can give any suggestions it would be greatly appreciated
Is the script doing all of that a local script?
its a server and local, heres the code
LOCAL ~
local uip = game:GetService("UserInputService")
local holdCropRE = game.ReplicatedStorage:WaitForChild("HoldCrop")
local releaseCropRE = game.ReplicatedStorage:WaitForChild("ReleaseCrop")
local plr = game.Players.LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local hum = char:FindFirstChild("Humanoid")
-- wait come down to the re
local camera = workspace.CurrentCamera
plr.CameraMode = Enum.CameraMode.LockFirstPerson
local raycastParams = RaycastParams.new()
raycastParams.FilterDescendantsInstances = {char}
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
local highlight = Instance.new("Highlight")
highlight.FillTransparency = 1
highlight.DepthMode = Enum.HighlightDepthMode.Occluded
uip.MouseIcon = "http://www.roblox.com/asset/?id=13580635690"
local objectBeingSelected --thing raycast hits
local mostRecentlyHeldObject --last held object
local isHoldingItem = false --are you holding something out right now?
game:GetService("RunService").Heartbeat:Connect(function()
objectBeingSelected = workspace:Raycast(camera.CFrame.Position, camera.CFrame.LookVector * 10, raycastParams)
-- move the crop both server side and locally
if isHoldingItem and mostRecentlyHeldObject then
local offset = camera.CFrame.LookVector * 5
mostRecentlyHeldObject.CFrame = mostRecentlyHeldObject.CFrame:Lerp(CFrame.new(camera.CFrame.Position + offset), 0.3)
holdCropRE:FireServer(camera.CFrame, mostRecentlyHeldObject)
end
-- determine which object to highlight
local objectToHighlight = nil
if isHoldingItem and mostRecentlyHeldObject then
objectToHighlight = mostRecentlyHeldObject
elseif objectBeingSelected and objectBeingSelected.Instance and objectBeingSelected.Instance:HasTag("Crop") then
objectToHighlight = objectBeingSelected.Instance
end
-- apply/clear highlight
if objectToHighlight then
highlight.Parent = objectToHighlight
highlight.Adornee = objectToHighlight
else
highlight.Parent = nil
highlight.Adornee = nil
end
if uip:IsKeyDown(Enum.KeyCode.V) then
uip.MouseBehavior = Enum.MouseBehavior.Default
end
end)
-- server sends all clients the position of the held item, and its owner
holdCropRE.OnClientEvent:Connect(function(ownedBy: Player, objectCFrame: CFrame, selectedObject: BasePart)
if ownedBy == plr then -- if i am the owner, ignore the server's request
print("owned by " .. tostring(ownedBy) .. " (me)")
else -- if i am not the owner, heed the server's request
print("owned by " .. tostring(ownedBy))
selectedObject.CFrame = objectCFrame
end
end)
uip.InputBegan:Connect(function(input: InputObject, gpe: boolean)
if gpe then return end
--if you click, drop/release object
if input.UserInputType == Enum.UserInputType.MouseButton1 then
if isHoldingItem then
-- DROPPING OBJECT
isHoldingItem = false
if mostRecentlyHeldObject then
mostRecentlyHeldObject.Anchored = false
mostRecentlyHeldObject.CanTouch = true
mostRecentlyHeldObject.AssemblyLinearVelocity = Vector3.new(0,0,0)
releaseCropRE:FireServer(mostRecentlyHeldObject, mostRecentlyHeldObject.CFrame)
mostRecentlyHeldObject = nil
end
elseif objectBeingSelected and objectBeingSelected.Instance and objectBeingSelected.Instance:HasTag("Crop") then
--PICKING UP OBJECT
isHoldingItem = true
mostRecentlyHeldObject = objectBeingSelected.Instance
mostRecentlyHeldObject.Anchored = true
mostRecentlyHeldObject.CanTouch = false
mostRecentlyHeldObject.CanCollide = true
if mostRecentlyHeldObject:GetAttribute("IsWelded") then
for i, v in mostRecentlyHeldObject.Parent:GetDescendants() do --assuming its welded to a model/union
if v:IsA("Weld") and v.Part1 == mostRecentlyHeldObject then
v:Destroy()
mostRecentlyHeldObject.Parent = workspace
end
end
end
end
end
end)
releaseCropRE.OnClientEvent:Connect(function(recentlyOwnedBy: Player, recentlySelectedObject: BasePart, recentObjectCFrame: CFrame)
if recentlyOwnedBy == plr then
print("owned by " .. tostring(recentlyOwnedBy) .. " (me)")
else
print("owned by " .. tostring(recentlyOwnedBy))
recentlySelectedObject.CFrame = recentObjectCFrame
recentlySelectedObject.Anchored = false
recentlySelectedObject.CanTouch = true
recentlySelectedObject.AssemblyLinearVelocity = Vector3.new(0,0,0)
end
end)
SERVER ~
local holdCrop = game.ReplicatedStorage:WaitForChild("HoldCrop")
local releaseCrop = game.ReplicatedStorage:WaitForChild("ReleaseCrop")
holdCrop.OnServerEvent:Connect(function(player: Player, cameraCFrame: CFrame, selectedObject: BasePart)
local offset = cameraCFrame.LookVector * 5
--selectedObject.CFrame = selectedObject.CFrame:Lerp(CFrame.new(cameraCFrame.Position + offset), 0.3)
--print(CFrame.new(cameraCFrame.Position + offset).Position)
selectedObject.Anchored = true
selectedObject.CanTouch = false
selectedObject.CanCollide = true
if selectedObject:GetAttribute("IsWelded") then
for i, v in selectedObject.Parent:GetDescendants() do --assuming its welded to a model/union
if v:IsA("Weld") and v.Part1 == selectedObject then
v:Destroy()
selectedObject.Parent = workspace
end
end
end
holdCrop:FireAllClients(player, CFrame.new(cameraCFrame.Position + offset), selectedObject)
end)
releaseCrop.OnServerEvent:Connect(function(player, selectedObject:BasePart, objectCFrame: CFrame)
selectedObject:SetAttribute("OwnedBy", player.Name)
selectedObject.Anchored = false
selectedObject.CFrame = objectCFrame
selectedObject.CanTouch = true
--selectedObject.AssemblyLinearVelocity = Vector3.new(0,0,0)
-- this is done client side now
releaseCrop:FireAllClients(player, selectedObject, objectCFrame)
end)
game.Players.PlayerAdded:Connect(function(plr)
local char = plr.Character or plr.CharacterAdded:Wait()
for _, v in char:GetDescendants() do
if v:IsA("BasePart") then
v.CollisionGroup = "Player"
end
end
end)
yeah its very messy
Make sure to set the NetworkOwnership of the part to the player (on server), part:SetNetworkOwner(plr)
this’ll allow changes like sliding the object on the client to be replicated on the server.
You’ll also need to set it back to nil part:SetNetworkOwner(nil)
or back to auto part:SetNetworkOwnershipAuto()
when you the player releases the object. Which one do you choose? Well I’ll choose auto since it’s less laggy however exploiters can take advantage of of stuff set to auto, or really anything they have networkownership of, honestly, shouldn’t worry about it too much.
Also why not use the built in DragDetectors by Roblox?
1 Like
Yeah, I don’t really know how to deal with this – I am not an experienced scripter, but still can script. Sorry, just let the other guy handle this with you.