Double-Tap to Run Does Not Work SPECIFICALLY with the W Key

My project has four states of movement:

  • Walking;
  • Jogging;
  • Running;
  • Dashing.

After a week of struggling, I managed to implement walking and jogging, and I’m now struggling with running.
Detecting if the player has pressed a key in a specific time window, and only calling the StartRunning() from the DefaultMovement module script (which handles WalkSpeed changes) when that key is pressed under the time window works — except when “that key” is W. I have no idea why, and I don’t even know how do I even begin on trying to figure this out.

Here follows the script.

-- InputHandler
local Players = game:GetService("Players");
local UserInputService = game:GetService("UserInputService");

local player = Players.LocalPlayer;
local character = player.Character or player.CharacterAdded:Wait();
local humanoid = character:WaitForChild("Humanoid");

local DefaultMovement = require(script.DefaultMovement);
local isWalking = false;
local isJogging = false;
local currentTick = 0;
local lastTick = currentTick;
local tickWindow = 0.8;

UserInputService.InputBegan:Connect(function(input)
	if isWalking == false and input.KeyCode == Enum.KeyCode.W then
		isWalking = true;
		warn("Is " .. player.Name .. " walking?");
		DefaultMovement.StartWalking();
		--
	elseif input.KeyCode == Enum.KeyCode.LeftShift then
		isWalking = false;
		isJogging = true;
		warn("Is " .. player.Name .. " jogging?");
		DefaultMovement.StopWalking();
		DefaultMovement.StartJogging();
		--
	elseif input.KeyCode == Enum.KeyCode.F and tick() - lastTick <= tickWindow then
		-- Tried replacing the W key with any other and it worked
		-- Does not work exclusively with W and I have no idea why 
		warn("Is " .. player.Name .. " running?");
		DefaultMovement.StartRunning();
	end
end)

UserInputService.InputEnded:Connect(function(input)
	if isWalking and input.KeyCode == Enum.KeyCode.W then
		isWalking = false;
		warn(player.Name .. " will stop walking.");
		DefaultMovement.StopWalking();
		lastTick = tick();
	elseif not isWalking and input.KeyCode == Enum.KeyCode.LeftShift then
		isWalking = true;
		isJogging = false;
		warn("——" .. player.Name .. " will stop jogging.");
		DefaultMovement.StopJogging();
	elseif not isJogging and input.KeyCode == Enum.KeyCode.F then
		warn("——" .. player.Name .. " will stop running.");
		DefaultMovement.StopRunning();
	end
end)

I’m genuinely desperate at this point.

1 Like

I’m sure there is a better way going about this, but I’m just gonna tell you what’s happening.

The line: if isWalking == false and input.KeyCode == Enum.KeyCode.W then is being triggerd every time because when you release “W” this line if isWalking and input.KeyCode == Enum.KeyCode.W then activates. So they go back and forth, which is why you never make it to elseif input.KeyCode == Enum.KeyCode.F and tick() - lastTick <= tickWindow then with a “W” key. So it goes, isWalking = true then isWalking = fasle reapeatedly, no matter how fast you press the keys, and only one if statement can be triggered so…

Basically I just changed some stuff around:

local Players = game:GetService("Players");
local UserInputService = game:GetService("UserInputService");

local player = Players.LocalPlayer;
local character = player.Character or player.CharacterAdded:Wait();
local humanoid = character:WaitForChild("Humanoid");

--local DefaultMovement = require(script.DefaultMovement);
local isWalking = false;
local isJogging = false;
local currentTick = 0;
local lastTick = currentTick;
local tickWindow = 0.8;

UserInputService.InputBegan:Connect(function(input)
	if input.KeyCode == Enum.KeyCode.W and tick() - lastTick <= tickWindow then
		-- Tried replacing the W key with any other and it worked
		-- Does not work exclusively with W and I have no idea why 
		warn("Is " .. player.Name .. " running?");
		--DefaultMovement.StartRunning();
	elseif isWalking == false and input.KeyCode == Enum.KeyCode.W then
		isWalking = true;
		warn("Is " .. player.Name .. " walking?");
		--DefaultMovement.StartWalking();
		--
		lastTick = tick();
	elseif input.KeyCode == Enum.KeyCode.LeftShift then
		isWalking = false;
		isJogging = true;
		warn("Is " .. player.Name .. " jogging?");
		--DefaultMovement.StopWalking();
		--DefaultMovement.StartJogging();
		--
	end
end)

UserInputService.InputEnded:Connect(function(input)
	if isWalking and input.KeyCode == Enum.KeyCode.W then
		isWalking = false;
		warn(player.Name .. " will stop walking.");
		--DefaultMovement.StopWalking();
		--lastTick = tick();
	elseif not isWalking and input.KeyCode == Enum.KeyCode.LeftShift then
		isWalking = true;
		isJogging = false;
		warn("——" .. player.Name .. " will stop jogging.");
		--DefaultMovement.StopJogging();
	elseif not isJogging and input.KeyCode == Enum.KeyCode.W then
		warn("——" .. player.Name .. " will stop running.");
		--DefaultMovement.StopRunning();
	end
end)

So we check the time-Window first, then we check if walking/jogging. Oh! And we added lastTick = tick(); to when the player is detected walking.

1 Like

Solved it, thank you!
I had figured out that the booleans were messing things up, though I had no idea on how to solve it. Never even considered changing the order.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.