How to check if player mouse button is still down after x seconds?

I am having an issue with a modified part dragging system where, if you click and release fast enough, the part will “glitch out” or select the baseplate / the part that appears upon dragging, which is not what I want. I was wondering if there is any way to modify my code to change it so that the first function will only run if the mouse is still held down after x seconds.

Code:

local Mouse = game.Players.LocalPlayer:GetMouse()
local Dragger = script.Parent.Dragger
local down = false
local selectedPart
Dragger.Parent = nil
Shift = false
Y = 0
RotY = 0
X = 0
RotX = 0
local Player = game.Players.LocalPlayer.Character
while Player == nil do
	Player = game.Players.LocalPlayer.Character
	wait()
end
--
YSpeed = 3
XSpeed = 3
--

Mouse.Button1Down:Connect(function()
	if Mouse.Target ~= nil and Player:FindFirstChild("Tool") == nil then
		if Mouse.Target:FindFirstChild("CanDrag") ~= nil then
			R = game.ReplicatedStorage.DragEvents.SetDrag:InvokeServer(Mouse.Target, true)
			if R == true then
				Dragger.CFrame = Mouse.Hit
				Dragger.Weld.Part1 = Mouse.Target
				selectedPart = Mouse.Target
				Dragger.Parent = game.Workspace
			end
		end
	end
end)

Mouse.Button1Up:Connect(function()
	if Mouse.Target == selectedPart then
		R = game.ReplicatedStorage.DragEvents.SetDrag:InvokeServer(Dragger.Weld.Part1, false)
		if R == true then
			selectedPart = nil
			Dragger.Weld.Part1 = nil
			Dragger.Parent = nil
			RotY = 0
			Y = 0
			X = 0
		end
	end
end)

game:GetService("UserInputService").InputBegan:Connect(function(Key)
	if Key.KeyCode == Enum.KeyCode.LeftShift then
		Shift = true
		Player.Humanoid.WalkSpeed = 0
	end
	if Key.KeyCode == Enum.KeyCode.W and Shift == true then
		Y = Y - YSpeed
	elseif Key.KeyCode == Enum.KeyCode.S and Shift == true then
		Y = Y + YSpeed
	end
	if Key.KeyCode == Enum.KeyCode.A and Shift == true then
		X = X + XSpeed
	elseif Key.KeyCode == Enum.KeyCode.D and Shift == true then
		X = X - XSpeed
	end
end)

game:GetService("UserInputService").InputEnded:Connect(function(Key)
	if Key.KeyCode == Enum.KeyCode.LeftShift then
		Shift = false
		Player.Humanoid.WalkSpeed = 16
		Y = 0
		X = 0
	end
	if Key.KeyCode == Enum.KeyCode.W and Shift == true then
		Y = Y + YSpeed
	elseif Key.KeyCode == Enum.KeyCode.S and Shift == true then
		Y = Y - YSpeed
	end
	if Key.KeyCode == Enum.KeyCode.A and Shift == true then
		X = X - XSpeed
	elseif Key.KeyCode == Enum.KeyCode.D and Shift == true then
		X = X + XSpeed
	end
end)

--

while true do
	wait()
	if Dragger.Weld.Part1 ~= nil then
		RotY = RotY + Y
		RotX = RotX + X
		CF1 = CFrame.new(Player.Head.CFrame.Position, Vector3.new(Mouse.Hit.X, Mouse.Hit.Y, Mouse.Hit.Z))
		CF2 = CF1 * CFrame.new(0, 0, -10)
		Dragger.BPos.Position = Vector3.new(CF2.X, CF2.Y, CF2.Z)
		Dragger.BGyro.CFrame = game.Workspace.CurrentCamera.CFrame * CFrame.Angles(math.rad(RotY), math.rad(RotX), 0)
	end
end

Error I am recieving:

Can only call Network Ownership API on a part that is descendent of Workspace  -  Client - DragAction:37

Anyone have any ideas?

1 Like

Maybe you should use ‘InputBegan’ instead of ‘MouseButton1Down’ and add a numbervalue that checks how much time passes

Hmm, I actually didn’t consider that. I will test that out right now and tell you if it works.

If you follow topic title then i would consider using tick() instead of creating objects that slightly waste memory, my guess is that something wrong with setting Network Ownership on a part.

I tried a version of this without implementing the cooldown and it does not seem to work. Here is the code;

uis.InputBegan:Connect(function(input, proc)
	if not proc then
		if input.KeyCode == Enum.UserInputType.MouseButton1 then
			if Mouse.Target ~= nil and Player:FindFirstChild("Tool") == nil then
				if Mouse.Target:FindFirstChild("CanDrag") ~= nil then
					R = game.ReplicatedStorage.DragEvents.SetDrag:InvokeServer(Mouse.Target, true)
					if R == true then
						Dragger.CFrame = Mouse.Hit
						Dragger.Weld.Part1 = Mouse.Target
						selectedPart = Mouse.Target
						Dragger.Parent = game.Workspace
					end
				end
			end
		end
	end
end)

uis.InputEnded:Connect(function(input, proc)
	if not proc then
		if input.KeyCode == Enum.UserInputType.MouseButton1 then
			if Mouse.Target == selectedPart then
				R = game.ReplicatedStorage.DragEvents.SetDrag:InvokeServer(Dragger.Weld.Part1, false)
				if R == true then
					selectedPart = nil
					Dragger.Weld.Part1 = nil
					Dragger.Parent = nil
					RotY = 0
					Y = 0
					X = 0
				end
			end
		end
	end
end)

It just doesn’t do anything now.

Yeah, this will only be used for moving single objects at a time but I guess the less memory lost the better.

Mousebutton is not a registered Enum item. Switch back to mouse.MouseButton1Down method

I switched it to input.UserInputType and it works, I will now try to implement the cooldown.

I’m having trouble implementing this. What I have currentely is setting a value to true when the input begins and checking if it is true, however this will still sometimes break. I’m not sure how to implement a cooldown without rewriting it entirely.

1 Like

If i get it correctly you need a cooldown between each clicks? It’s confusing for me.

No, I need to have it so the part of the script will only run if the player is still holding down the mouse btn 1 after x amount of seconds.

Put all the necessary code in a function and do this(it’s not reliable so yeah, it is what it is):

local CanDrag=true

uis.InputBegan:Connect(function(inp, p)
if inp.UserInputType == Enum.UserInputType.MouseButton1 and not p and Mouse.Target and not Player:FindFirstChild("Tool") and CanDrag~=false then
CanDrag=true
coroutine.wrap(function()
local timer = tick()
repeat
if tick()-timer >= 1 then-- Change time preference here
Drag()--name of the function specifically and values to use
end
wait()
until CanDrag == false
end)()
end
end)

(Im writing this on a mobile device dont judge me, alright?)

Unfortunately, this doesn’t work. Have any other ideas? (the grabbing never starts)

Can you show me a snippet of your function code

Sure;

local CanDrag=true

local function drag()
	if Mouse.Target ~= nil and Player:FindFirstChild("Tool") == nil then
		if Mouse.Target:FindFirstChild("CanDrag") ~= nil and down == true then
			R = game.ReplicatedStorage.DragEvents.SetDrag:InvokeServer(Mouse.Target, true)
			if R == true then
				Dragger.CFrame = Mouse.Hit
				Dragger.Weld.Part1 = Mouse.Target
				selectedPart = Mouse.Target
				Dragger.Parent = game.Workspace
				wait(0.1)
			end
		end
	end
end

uis.InputBegan:Connect(function(inp, p)
	if inp.UserInputType == Enum.UserInputType.MouseButton1 and not p and Mouse.Target and not Player:FindFirstChild("Tool") and CanDrag==false then
		coroutine.wrap(function()
			local timer = tick()
			repeat
				if tick()-timer >= 0.3 then-- Change time preference here
					drag()--name of the function specifically and values to use
				end
				wait()
			until CanDrag == false
		end)()
	end
end)

I have edited the code try again please. Also sorry for all my flawless mistakes, since im typing on a mobile device.

Still does not work, however could you not implement the tick() function into the other code which was working?

I edited code once again, and i dont think so because you’d have to loop check if subdivision is correct. Please reply if something is wrong because it’s really hard to type on mobile😓

Again, this still does not work. Also, what do you mean loop check if subdivision is correct?

What i meant is, this part

tick()-timer >=1