How to check how long a player has pressed a button and run a loop

hello, im trying to make a system where it rotates a Model when the player clicks the E button on his keyboard, and it rotates the Model 5 degrees, the problem here is that 5 degrees is slow so i want to make a system that when the player holds down the E key for 1.5 seconds then it starts adding 5 rapidly until the player lift his finger off the E key

so how can i check how long the player has pressed a key, because i tried using a while loop but the problem is that it glitches when the player spams the E key

heres my script:

-- Local script

local Cooldown = false
local Model = script.Parent

local UserInputService = game:GetService("UserInputService")

UserInputService.InputBegan:Connect(function(input, gameProccesedEvent) ---- furniture rotation 
 if input.KeyCode == Enum.KeyCode.E  and Cooldown == false then

	Cooldown = true
	local rotation = CFrame.Angles(0, math.rad(-5), 0)
	local modelCFrame = Model:GetPivot()

	Model:PivotTo(modelCFrame * rotation)

	wait(.1)

	Cooldown = false
		
 end
end)

any help will be appreciated

1 Like

this seems like it has already been semi-answered.

3 Likes

yes i have seen that topic, but its not my question,

that topic’s answer only shows how long you have held down the mouse button when you stop holding it down, i want while its down the tick() adds until it reaches 1.5 and then it starts a loop

also i have tried reworking that solution but i was stumped lol

oh sorry lol, i just saw the title and was like: “oh this has already been answered??”

1 Like

no its alright thanks for trying to help

maybe make a variable that is called: CurrentlyHeld, this variable being a bool

when the input begin is fired change this to true

when the input ended is fired change this to false

and inside of the

you can do

task.wait(1.5)
if CurrentlyHeld then
repeat 
--stuff
task.wait(.1)
until not CurrentlyHeld
end --sorry forgot about the repeat of doing it

the problem here is that idk what to put in the “-- suff”

because i though to put a while holdingdown == true do but when the player spams the E key it glitches and makes the loop run faster

i have tried it but it didnt work


local Model = workspace["Basic Table"]

local UserInputService = game:GetService("UserInputService")
local HoldingDown = false

UserInputService.InputBegan:Connect(function(input, gameProccesedEvent) ---- furniture rotation 
	if input.KeyCode == Enum.KeyCode.E then
		
		HoldingDown = true
		
		local rotation = CFrame.Angles(0, math.rad(-5), 0)
		local modelCFrame = Model:GetPivot()

		Model:PivotTo(modelCFrame * rotation)

		task.wait(1.5)
		if HoldingDown then
			--stuff
			while HoldingDown == true do
			local rotation = CFrame.Angles(0, math.rad(-5), 0)
			local modelCFrame = Model:GetPivot()

			Model:PivotTo(modelCFrame * rotation)
			wait(.3)
			end
		end

	end
end)

UserInputService.InputEnded:Connect(function(input, gameProccesedEvent) ---- furniture rotation 
	
	if input.KeyCode == Enum.KeyCode.E then
		
		HoldingDown = false
		
	end
end)

inside the stuff is where you would put the repeating rotation until let go of, but i just remembered that the while true would yield the whole script

local Model = workspace["Basic Table"]

local UserInputService = game:GetService("UserInputService")
local HoldingDown = false

local function begincheck()
task.wait(1.5)
		if HoldingDown then
			--stuff
			while HoldingDown == true do
			local rotation = CFrame.Angles(0, math.rad(-5), 0)
			local modelCFrame = Model:GetPivot()

			Model:PivotTo(modelCFrame * rotation)
			task.wait(.3)
			end
		end
end

UserInputService.InputBegan:Connect(function(input, gameProccesedEvent) ---- furniture rotation 
	if input.KeyCode == Enum.KeyCode.E then
		HoldingDown = true
        task.spawn(begincheck)
	end
end)

UserInputService.InputEnded:Connect(function(input, gameProccesedEvent) ---- furniture rotation 
	if input.KeyCode == Enum.KeyCode.E then
		HoldingDown = false
	end
end)

maybe i should use coroutine??

ill try it now and see

same glitch happening when i spam the E button it rotates faster, it repeats as if the task.wait is task.wait(.01)

i dont know then, sorry (i dont usually do stuff like this (rotations, input reading, blah), and i wanted to see if i could help and to see if i am able to figure it out)

but gl man

1 Like

me too thats why im confused, but its alright appreciate the help, ill make this topic open if i dont an answer ill probably discard it all because its not that neccessary in my game

local rotation_started = false
local rotation_speed = math.rad(5) --deg/s
local current_rotation = 0
local function Rotate()
  while(rotation_started) do
    --how much time passed
    local delta_time = task.wait()
    current_rotation += rotation_speed * delta_time --makes speed consistant
    --rotates around yaw
    local rotation_cframe = CFrame.fromAxisAngle(Vector3.yAxis, current_rotation)
    --sets the model at the same position with new rotation
    model:PivotTo(rotation_cframe + model:GetPivot().Position)
  end
end

UserInputService.InputBegan ...
rotation_started = true
--creates a coroutine
coroutine.wrap(Rotate)()


UserInputService.InputEnded ...
--will disable coroutine next frame
rotation_started = false

Is this what you are looking for?

1 Like

im testing it right now, im altering it a little bit because its not EXACTLY what i want but thanks

2 Likes

This is what i’ve got from what you said, hopefully it’s what you are looking for.

local Model = -- reference to your model
local UserInputService = game:GetService("UserInputService")

local rotationSpeed = math.rad(5)
local accelerationRate = 0.02
local initialDelay = 1.5
local repeatDelay = 0.1

local isKeyPressed = false
local keyPressedTime = 0

local function rotateModel()
	local rotation = CFrame.Angles(0, rotationSpeed, 0)
	if Model:IsA("Model") then
		local modelCFrame = Model.PrimaryPart.CFrame
		Model:PivotTo(modelCFrame * rotation)
	elseif Model:IsA("BasePart") then
		local modelCFrame = Model.CFrame
		Model.CFrame = modelCFrame * rotation
	end
end

UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
	if input.KeyCode == Enum.KeyCode.E then
		isKeyPressed = true
		keyPressedTime = tick()
	end
end)

UserInputService.InputEnded:Connect(function(input)
	if input.KeyCode == Enum.KeyCode.E then
		isKeyPressed = false
		rotationSpeed = math.rad(5)
	end
end)

game:GetService("RunService").Heartbeat:Connect(function()
	if isKeyPressed then
		local elapsedTime = tick() - keyPressedTime
		if elapsedTime >= initialDelay then
			rotationSpeed += math.rad(rotationSpeed + accelerationRate)
		end
		rotateModel()
		task.wait(repeatDelay)
	end
end)
1 Like

everybody seems to be drifitng away from the actual problem, although i appreciate the efforts but thats 50% of my question, your solution only rotates the model instantly after holding down E, i want it to wait 1.5 seconds and THEN it rotates the model, and if the player stops holding down within the 1.5 seconds then it breaks the loop or stops the rotating rapidly

1 Like

It now waits 1.5 seconds before rotating / gradually increasing its speed

local Model = -- reference to ur model / part
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")

local holdStartTime = nil
local baseRotationSpeed = math.rad(2)
local rotationSpeed = baseRotationSpeed

UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
	if input.KeyCode == Enum.KeyCode.E and not gameProcessedEvent then
		holdStartTime = tick()
	end
end)

UserInputService.InputEnded:Connect(function(input)
	if input.KeyCode == Enum.KeyCode.E then
		holdStartTime = nil
		rotationSpeed = baseRotationSpeed
	end
end)

RunService.RenderStepped:Connect(function(deltaTime)
	if holdStartTime then
		local holdDuration = tick() - holdStartTime
		if holdDuration >= 1.5 then

			rotationSpeed = rotationSpeed + math.rad(5) * deltaTime
			local rotation = CFrame.Angles(0, rotationSpeed, 0)
			if Model:IsA("Model") then
				local modelCFrame = Model.PrimaryPart.CFrame
				Model:PivotTo(modelCFrame * rotation)
			elseif Model:IsA("BasePart") then
				local modelCFrame = Model.CFrame
				Model.CFrame = modelCFrame * rotation
			end
		end
	end
end)
1 Like

that worked, but how can i make it a set rotation value, not gradually increasing, i just want it to rotate 5 without any acceleration

1 Like

change
rotationSpeed = rotationSpeed + math.rad(5) * deltaTime
to
rotationSpeed = math.rad(5)

That should work.

1 Like

appreciate it finally found a solution

2 Likes