Issue with Sprint System Compatibility with Mobile Devices

Hi there,

As the title suggests, I am trying to create a sprint system that considers mobile devices (in addition to computers).

I have based the system on my original sprinting mechanic, which involves stamina loss and an exhaustion state (used UserInputService), but the script I have does not work (ContextActionService). There is no error in the output, and I am also at a loss for what to do.

Script:

local Player = game.Players.LocalPlayer
local Character = Player.Character
local Humanoid = Character:FindFirstChildOfClass("Humanoid")

local ContextActionService = game:GetService("ContextActionService")

local Stamina = 100
local RunRefresh = 20 -- minimum level to allow sprinting after exhausted

local Running = false
local Exhausted = false


local function Sprinting(Action, GPE, InputState)
	if Action == "Sprinting" and InputState == Enum.UserInputState.Begin and not GPE then
		if Exhausted then return end
		Running = true
		Humanoid.WalkSpeed = 28
		while Running do
			if Stamina > 0 then
				Stamina -= 0.25
				script.Parent:TweenSize(UDim2.new(Stamina / 100, 0, 1, 0), "Out", "Linear", 0)
			else
				Exhausted = true
				Humanoid.WalkSpeed = 16
				break
			end
			task.wait() -- delay between stamina loss
		end
		
	elseif Action == "Sprinting" and InputState == Enum.UserInputState.End and not GPE then
		Running = false
		Humanoid.WalkSpeed = 16
	end
end
	

task.spawn(function() -- task.spawn used to not yield code
	while true do
		if Stamina < 100 and not Running then -- 46 seconds until Stamina = 100
			Stamina += 0.075
			script.Parent:TweenSize(UDim2.new(Stamina / 100, 0, 1, 0), "Out", "Linear", 0)
			task.wait() -- delay between stamina gain
			Exhaustion()
		end
		task.wait()
	end
end)

function Exhaustion()
	if Stamina > RunRefresh then -- we can now run again!
		Exhausted = false
	end
end

ContextActionService:BindAction("Sprinting", Sprinting, true, Enum.KeyCode.LeftShift)

Derived Post: https://devforum.roblox.com/t/sprint-for-mobile-and-console/

The script used the wrong service to detect keyboard input. Instead of using ContextActionService, it should use UserInputService.

The conditions for checking the input state were incorrect in the original script. They have been fixed in the modified script to correctly handle the start and end of the key press.

The Exhaustion function was placed in the wrong location in the original script, causing it to be called multiple times per frame. It has been moved to the correct location so that it is called once per frame.

local Player = game.Players.LocalPlayer
local Character = Player.Character
local Humanoid = Character:FindFirstChildOfClass("Humanoid")

local UserInputService = game:GetService("UserInputService")

local Stamina = 100
local RunRefresh = 20 -- minimum level to allow sprinting after exhausted

local Running = false
local Exhausted = false

local function Sprinting(Action, InputState)
	if Action == "Sprinting" and InputState == Enum.UserInputState.Begin then
		if Exhausted then return end
		Running = true
		Humanoid.WalkSpeed = 28
		while Running do
			if Stamina > 0 then
				Stamina -= 0.25
				script.Parent:TweenSize(UDim2.new(Stamina / 100, 0, 1, 0), "Out", "Linear", 0)
			else
				Exhausted = true
				Humanoid.WalkSpeed = 16
				break
			end
			task.wait() -- delay between stamina loss
		end
	elseif Action == "Sprinting" and InputState == Enum.UserInputState.End then
		Running = false
		Humanoid.WalkSpeed = 16
	end
end

task.spawn(function()
	while true do
		if Stamina < 100 and not Running then -- 46 seconds until Stamina = 100
			Stamina += 0.075
			script.Parent:TweenSize(UDim2.new(Stamina / 100, 0, 1, 0), "Out", "Linear", 0)
		end
		Exhaustion()
		task.wait()
	end
end)

function Exhaustion()
	if Stamina > RunRefresh then -- we can now run again!
		Exhausted = false
	end
end

UserInputService.InputBegan:Connect(function(input, processed)
	if not processed and input.KeyCode == Enum.KeyCode.LeftShift then
		Sprinting("Sprinting", Enum.UserInputState.Begin)
	end
end)

UserInputService.InputEnded:Connect(function(input, processed)
	if not processed and input.KeyCode == Enum.KeyCode.LeftShift then
		Sprinting("Sprinting", Enum.UserInputState.End)
	end
end)

The modified script now includes input event handlers (InputBegan and InputEnded) that accurately detect the LeftShift key press and release. These event handlers trigger the sprinting action accordingly.

1 Like

Thanks for the help! :happy3:

I apologise for the late reply, but there are some errors presented in the output that I will relay to you:

task.spawn(function()
	while true do
		if Stamina < 100 and not Running then -- 46 seconds until Stamina = 100
			Stamina += 0.075
			script.Parent:TweenSize(UDim2.new(Stamina / 100, 0, 1, 0), "Out", "Linear", 0)
		end
		Exhaustion() -- upon spawn, the player is received an error here: attempt to call a nil value
		task.wait()
	end
end)

The next issues may be a consequence of the problem above, but I figure it is important to convey them, too!

local function Sprinting(Action, InputState)
	if Action == "Sprinting" and InputState == Enum.UserInputState.Begin then
		if Exhausted then return end
		Running = true
		Humanoid.WalkSpeed = 28 -- When the Player begins Sprinting: attempt to index nil with 'WalkSpeed'
		while Running do
			if Stamina > 0 then
				Stamina -= 0.25
				script.Parent:TweenSize(UDim2.new(Stamina / 100, 0, 1, 0), "Out", "Linear", 0)
			else
				Exhausted = true
				Humanoid.WalkSpeed = 16 -- When the Player stops Sprinting: attempt to index nil with 'WalkSpeed'
				break
			end
			task.wait()
		end
	elseif Action == "Sprinting" and InputState == Enum.UserInputState.End then
		Running = false
		Humanoid.WalkSpeed = 16
	end
end

Make sure that you are accessing the correct humanoid object. Instead of using Character:FindFirstChildOfClass("Humanoid"), you can directly access it using Character.Humanoid. Update the following line:

local Humanoid = Character:FindFirstChildOfClass("Humanoid")

to:

local Humanoid = Character.Humanoid

Additionally, ensure that the Character object is not nil. You can add a check to make sure that the Character object exists before accessing the Humanoid property. Modify the line:

local Character = Player.Character

to:

local Character = Player.Character or Player.CharacterAdded:Wait()

Tell me if this works :slight_smile:

1 Like

Works well so far!

Just got an issue: the player’s stamina does not regenerate, and I am receiving an error in a block, which I have attached below:

task.spawn(function()
	while true do
		if Stamina < 100 and not Running then
			Stamina += 0.075
			script.Parent:TweenSize(UDim2.new(Stamina / 100, 0, 1, 0), "Out", "Linear", 0)
		end
		ExhaustionRecovery() -- attempt to call a nil value
		task.wait()
	end
end)

function ExhaustionRecovery() -- Changed function name for clarity
	if Stamina > RunRefresh then
		Exhausted = false
	end
end

This is displayed in the output as soon as the player joins.

Wrong, the OP needs this system compatible with mobile so he should use ContextActionService rather than UserInputService

Ok, well because of some complications with the stamina system, it is entirely possible I sent in a dysfunctional script as I attempted to create one using ContextActionService in my original post.

Therefore, I will send in my original sprinting mechanic. How would I turn this sprinting system to be compatible with mobile devices?

local Player = game.Players.LocalPlayer
local Character = Player.Character

local UserInputService = game:GetService("UserInputService")

local Stamina = 100
local RunRefresh = 20 -- when to allow running after exhausted

local Running = false
local Exhausted = false

UserInputService.InputBegan:Connect(function(Input, gPE)
	if Player.Team.Name == "Agents" then -- Did not mention in my original post as it is not necessary, but I will add it for extra context
		if (Input.KeyCode == Enum.KeyCode.LeftShift) and not gPE then
			if Exhausted then return end
			Running = true
			Player.Character.Humanoid.WalkSpeed = 32
			while Running do
				if Stamina > 0 then
					Stamina -= 0.25
					script.Parent:TweenSize(UDim2.new(Stamina / 100, 0, 1, 0), "Out", "Linear", 0)
				else
					Exhausted = true
					Player.Character.Humanoid.WalkSpeed = 16
					break
				end
				task.wait()
			end
		end
	end
end)

UserInputService.InputEnded:Connect(function(Input, gPE)
	if (Input.KeyCode == Enum.KeyCode.LeftShift) and not gPE then
		Running = false
		Player.Character.Humanoid.WalkSpeed = 16
	end
end)

task.spawn(function() -- Not yield code
	while true do
		if Stamina < 100 and not Running then
			Stamina += 0.075
			script.Parent:TweenSize(UDim2.new(Stamina / 100, 0, 1, 0), "Out", "Linear", 0)
			task.wait() -- Delay between stamina gain
			Exhaustion()
		end
		task.wait()
	end
end)

function Exhaustion()
	if Stamina > RunRefresh then -- Player may run again
		Exhausted = false
	end
end

Replace this with:

local function Sprint(_, state)
    if state == Enum.UserInputState.Begin then
        if Player.Team.Name == "Agents" then
			if Exhausted then return end
			Running = true
			Player.Character.Humanoid.WalkSpeed = 32

			while Running do
				if Stamina > 0 then
					Stamina -= 0.25
					script.Parent:TweenSize(UDim2.new(Stamina / 100, 0, 1, 0), "Out", "Linear", 0)
				else
					Exhausted = true
					Player.Character.Humanoid.WalkSpeed = 16
					break
				end

				task.wait()
			end
		end
    elseif state == Enum.UserInputState.End then
        Running = false
		Player.Character.Humanoid.WalkSpeed = 16
    end
end

ContextActionService:BindAction("Sprint", Sprint, true, Enum.KeyCode.LeftShift)
ContextActionService:SetPosition("Sprint", UDim2.new(0.9, 0, 0.8, 0))
ContextActionService:SetTitle("Sprint")
1 Like

I am getting this error message with the last line:

ContextActionService:SetTitle(Sprint) -- Argument 2 missing or nil

Reviewing the page for ContextActionService, it seems to be missing some designated text for the ui button, but when I change it (e.g., Sprint, "Sprint"), I receive this error message:

ContextActionService could not find the function passed in, doing nothing.

Mb

ContextActionService:SetTitle("Sprint", "Sprint")
1 Like

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