UserInputService: player movements

Lesson#23 of 23 in project Theory

Example code

-- LocalScript: runs on each player's device so it can read keyboard input.
-- StarterPlayerScripts copies this into the player when they join.

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

local player = Players.LocalPlayer

local WALK_SPEED = 16
local SPRINT_SPEED = 24
local JUMP_COOLDOWN = 0.2

local humanoid: Humanoid? = nil
local canDoubleJump = false
local hasDoubleJumped = false
local jumpReleasedSinceLastJump = true

local function applyWalkSpeed()
	if not humanoid then
		return
	end

	if UserInputService:IsKeyDown(Enum.KeyCode.LeftShift) then
		humanoid.WalkSpeed = SPRINT_SPEED
	else
		humanoid.WalkSpeed = WALK_SPEED
	end
end

local function onCharacterAdded(character)
	local newHumanoid = character:WaitForChild("Humanoid")
	humanoid = newHumanoid
	canDoubleJump = false
	hasDoubleJumped = false
	jumpReleasedSinceLastJump = true
	applyWalkSpeed()

	newHumanoid.StateChanged:Connect(function(_oldState, newState)
		if newHumanoid ~= humanoid then
			return
		end

		if newState == Enum.HumanoidStateType.Landed then
			canDoubleJump = false
			hasDoubleJumped = false
			
		elseif newState == Enum.HumanoidStateType.Freefall then
			task.delay(JUMP_COOLDOWN, function()
				if newHumanoid == humanoid and newHumanoid:GetState() == Enum.HumanoidStateType.Freefall then
					canDoubleJump = true
				end
			end)
		end
	end)
end

UserInputService.InputBegan:Connect(function(input, gameProcessed)
	if gameProcessed then
		return
	end

	if input.KeyCode == Enum.KeyCode.LeftShift then
		applyWalkSpeed()
	end
end)

UserInputService.InputEnded:Connect(function(input)
	if input.KeyCode == Enum.KeyCode.LeftShift then
		applyWalkSpeed()
	elseif input.KeyCode == Enum.KeyCode.Space then
		jumpReleasedSinceLastJump = true
	end
end)

-- JumpRequest fires for Space on keyboard and the jump button on other devices.
UserInputService.JumpRequest:Connect(function()
	if not humanoid or humanoid:GetState() == Enum.HumanoidStateType.Dead then
		return
	end

	if canDoubleJump and not hasDoubleJumped and jumpReleasedSinceLastJump then
		hasDoubleJumped = true
		jumpReleasedSinceLastJump = false
		humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
		return
	end

	jumpReleasedSinceLastJump = false
end)

-- cover all the cases where the character is added
if player.Character then
	onCharacterAdded(player.Character)
end

player.CharacterAdded:Connect(onCharacterAdded)

Objectives

  1. #1
  2. #2
  3. #3
  4. #4
  5. #5
  6. #6
  7. #7