How do I smoothly rotate a part with player inputs?

I have a part which I want to rotate left or right when the player clicks “A” or “D”. I’ve tried using RunService.Heartbeat, but I don’t get desirable results. The first time I click “A” or “D”, it rotates perfectly fine, but when I click the second, third time and so on, it, doubles, triples the speed each time, that’s not what I want, and I don’t know how to fix it. Here’s my code:

local tankController = {}

local runService = game:GetService("RunService")

local turningLeft
local turningRight
function tankController.turnLeft()
	turningLeft = true
	runService.Heartbeat:Connect(function(dt)
		if turningLeft == true then
			game.Workspace.testTank.CFrame = game.Workspace.testTank.CFrame * CFrame.fromEulerAnglesXYZ(0,0.05,0 * dt)
		else return end
	end)
end

function tankController.stopTurningLeft()
	turningLeft = false
end

function tankController.turnRight()
	turningRight = true
	runService.Heartbeat:Connect(function(dt)
		if turningRight == true then
			game.Workspace.testTank.CFrame = game.Workspace.testTank.CFrame * CFrame.fromEulerAnglesXYZ(0,-0.05,0 * dt)
		else return end	
	end)
end

function tankController.stopTurningRight()
	turningRight = false
end

return tankController

What you could do is make it lerp:

local tankController = {}

local runService = game:GetService("RunService")

local turningLeft
local turningRight
function tankController.turnLeft()
	turningLeft = true
	runService.Heartbeat:Connect(function(dt)
		if turningLeft == true then
			game.Workspace.testTank.CFrame = game.Workspace.testTank.CFrame:Lerp(game.Workspace.testTank.CFrame * CFrame.fromEulerAnglesXYZ(0,0.05,0 * dt), 0.3)
		else return end
	end)
end

function tankController.stopTurningLeft()
	turningLeft = false
end

function tankController.turnRight()
	turningRight = true
	runService.Heartbeat:Connect(function(dt)
		if turningRight == true then
			game.Workspace.testTank.CFrame = game.Workspace.testTank.CFrame:Lerp(game.Workspace.testTank.CFrame * CFrame.fromEulerAnglesXYZ(0,-0.05,0 * dt), 0.3)
		else return end	
	end)
end

function tankController.stopTurningRight()
	turningRight = false
end

return tankController

Same thing happens. It speeds up when clicking the key multiple times.

Ah I see, you connect the movement to heartbeat each time you press the keys.


local runService = game:GetService("RunService")

local turningLeft

local turningRight

runService.Heartbeat:Connect(function(dt)

if turningRight == true then

game.Workspace.testTank.CFrame = game.Workspace.testTank.CFrame * CFrame.fromEulerAnglesXYZ(0,-0.05,0 * dt)

end

if turningLeft == true then

game.Workspace.testTank.CFrame = game.Workspace.testTank.CFrame * CFrame.fromEulerAnglesXYZ(0,0.05,0 * dt)

end

end)

function tankController.turnLeft()

turningLeft = true

end

function tankController.stopTurningLeft()

turningLeft = false

end

function tankController.turnRight()

turningRight = true

end

function tankController.stopTurningRight()

turningRight = false

end

return tankController

Here, i made it only be in one loop for ya :stuck_out_tongue:

1 Like

It speeds up because you’re making a new connection every time you press the same key twice, Instead you should instead have one render stepped connection in general that starts on require (e.g outside of function scope but just below the table creation in the module)
And moves based on the current key pressed, OR you can manipulate the turning left and turning right variables to also turn it.

Point being don’t make multiple connections like that, it’s inefficient, a memory leak and overall a bad idea instead use one single connection that adaptively turns based on the variables or whatever key is down.

1 Like

Ooooh, I understand now, I’m not that experienced at programming yet so no big surprise I made a stupid mistake like this, big thanks :stuck_out_tongue: (It works perfectly now btw)

I understand what I’ve done wrong now, both thanks to you and @dokso, thanks for your time :slight_smile: