Drag script is laggy

i followed a tutorial on how to drag parts with mouse except its laggy and floats in the air when i release the part its also only client sided and i want to make it server sided

To Do List:

  • Reduce Lag
  • Server-Side
-- Services
local uis = game:GetService("UserInputService")
local workspace = game:GetService("Workspace")

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local DragEvent = ReplicatedStorage:WaitForChild("DragEvent")


-- Variables
local picked_up_part = false
local part = nil

local Localplayer = game.Players.LocalPlayer
local character = Localplayer.Character

uis.InputBegan:Connect(function(input)
	local characterPosition = character.PrimaryPart.Position
	local ray = workspace.CurrentCamera:ViewportPointToRay(uis:GetMouseLocation().X, uis:GetMouseLocation().Y)

	if input.UserInputType == Enum.UserInputType.MouseButton1 and not picked_up_part then
		for i, v in pairs(workspace:GetDescendants()) do
			if v:HasTag("Item") and (ray.Origin + ray.Direction * (ray.Origin - v.Position).Magnitude - v.Position).Magnitude <= 1 then
				picked_up_part = true
				part = v
				local connection = nil
				connection = game:GetService("RunService").Heartbeat:Connect(function()
					if not picked_up_part then connection:Disconnect() return end
					local ray = workspace.CurrentCamera:ViewportPointToRay(uis:GetMouseLocation().X, uis:GetMouseLocation().Y)
					part.CanCollide = false
					
					local lookVector = (workspace.CurrentCamera.CFrame.Position - part.Position).Unit
					part.CFrame = CFrame.lookAt(ray.Origin + ray.Direction * 6, characterPosition)
					DragEvent:FireServer({partName = part.Name, position = part.Position})
				end)
			end
		end
	elseif input.UserInputType == Enum.UserInputType.MouseButton2 and picked_up_part then
		-- Release the picked up part
		picked_up_part = false
		part.CanCollide = true
		part = nil
	end
end)
5 Likes

The lag might be from the heartbeat connection so try doing renderstepped instead, I’m not very experienced with drag scripts so idk if it will work or if it’s the best solution

3 Likes

no i tried that its not the problem

3 Likes

Maybe because of the DragEvent?

Remote Events take up some memory and calling it every heartbeat (as @Blackhole2670 said) could be affecting performance.

5 Likes

yeah i did figure that out but its like frozen in the air and wont move till i push it and when i do push it it flys away

4 Likes

Well what does the remote event do? Removing it entirely can affect the script actually being able to function.

4 Likes

the remote event isnt the problem but its meant to set the network ownership to the player which i never even did thats why i added server-side to the list the script functions it just freezes in the air until i push it with my character

3 Likes

Something as simple as a Remote event can be causing the lag due to how often it’s being fired. You probably want to first check the network ownership of the part you’re dragging, if it’s not set to the player fire the remote event. If it is, don’t fire it. This will prevent the remote event being fired over and over despite the network ownership already being set.

4 Likes

Exactly, try firing the server every 10 heartbeats (0.1) seconds.
This would reduce lag as well as it would also be accurate on the server side.

2 Likes

Try this:

-- Services
local uis = game:GetService("UserInputService")
local workspace = game:GetService("Workspace")
local CollectionService = game:GetService("CollectionService")

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local DragEvent = ReplicatedStorage:WaitForChild("DragEvent")


-- Variables
local picked_up_part = false
local part = nil

local Localplayer = game.Players.LocalPlayer
local character = Localplayer.Character

uis.InputBegan:Connect(function(input)
	local characterPosition = character.PrimaryPart.Position
	local ray = workspace.CurrentCamera:ViewportPointToRay(uis:GetMouseLocation().X, uis:GetMouseLocation().Y)

	if input.UserInputType == Enum.UserInputType.MouseButton1 and not picked_up_part then
		for _, v in CollectionService:GetTagged("Item") do
			if (ray.Origin + ray.Direction * (ray.Origin - v.Position).Magnitude - v.Position).Magnitude <= 1 then
				picked_up_part = true
				part = v
				local connection = nil
				connection = game:GetService("RunService").Heartbeat:Connect(function()
					if not picked_up_part then connection:Disconnect() return end
					local ray = workspace.CurrentCamera:ViewportPointToRay(uis:GetMouseLocation().X, uis:GetMouseLocation().Y)
					part.CanCollide = false

					local lookVector = (workspace.CurrentCamera.CFrame.Position - part.Position).Unit
					part.CFrame = CFrame.lookAt(ray.Origin + ray.Direction * 6, characterPosition)
					DragEvent:FireServer({partName = part.Name, position = part.Position})
				end)
			end
		end
	elseif input.UserInputType == Enum.UserInputType.MouseButton2 and picked_up_part then
		-- Release the picked up part
		picked_up_part = false
		part.CanCollide = true
		part = nil
	end
end)

You should not be looping through everything in the workspace every frame.

4 Likes

it still gets stuck in the air
but im sure this is probably more optimal
image

3 Likes

i would suggest changing the networkownership to nil then since the player tries to update the psysics but you are trying to overide the physics so it makes it do exactly that

1 Like

i tried that too but it still freezes

2 Likes

i want to position where ever the player lets go of it

2 Likes

and i tried to do what you said but now its saying

SetNetworkOwnership is not a valid member of Part "Workspace.Part"
2 Likes

the server script is this what you asked for?

local DragRemote = game:GetService("ReplicatedStorage"):WaitForChild("DragEvent")

DragRemote.OnServerEvent:Connect(function(player, targetPart)
	if targetPart:FindFirstAncestorOfClass("Model") and targetPart:FindFirstAncestorOfClass("Model"):FindFirstChildWhichIsA("BasePart") then
		local targetModel = targetPart:FindFirstAncestorOfClass("Model")
		for _, part in ipairs(targetModel:GetChildren()) do
			if part:IsA("BasePart") then
				part:SetNetworkOwnership(player)
			elseif part:IsA("MeshPart") then
				part:SetNetworkOwnership(player)
			end
		end
	end
end)
2 Likes

Sorry to ask but couldn’t you just use DragDetectors for your use case? Announcing DragDetectors! You can use them to drag parts… as implied by the name

2 Likes

yeah but i wanted to try and make my own

1 Like