Issue with CAS actions clashing with each other

Hello,

I’m currently designing a relatively simple run and crouching system, but I encountered a problem with the actions clashing with each other. If I run, crouch, and then let go of the run button while still holding the crouch button I go down to default walkspeed, then immediately down to crouching speed. The same applies in the reverse. I have made countless running and crouching systems in the past, but only with the UserInputService, and I would like to experiment with the ContextActionService.

Any ideas?

Here’s the code:

local cas = game:GetService("ContextActionService")

local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()

local walkSpeed = character:WaitForChild("Humanoid").WalkSpeed
local runSpeed, crouchSpeed = character.Humanoid.WalkSpeed + 5, character.Humanoid.WalkSpeed - 10

local running = false

local crouching, sliding = false, false

local function run(action, inputState)
	if action == "run" and inputState == Enum.UserInputState.Begin then
		if not running then
			running = true
			
			if crouching then
				crouching = false
			end
			
			character.Humanoid.WalkSpeed = runSpeed
		end
	elseif inputState == Enum.UserInputState.End then
		running = false

		character.Humanoid.WalkSpeed = walkSpeed
	end
end

local function crouch(action, inputState)
	if action == "crouch" and inputState == Enum.UserInputState.Begin then
		if not crouching and not running then
			crouching = true
			
			character.Humanoid.WalkSpeed = crouchSpeed
		end
	elseif inputState == Enum.UserInputState.End then
		crouching = false
		
		if not running then
			character.Humanoid.WalkSpeed = walkSpeed
		end
	end
end

cas:BindAction("run", run, false, Enum.KeyCode.LeftShift)
cas:BindAction("crouch", crouch, false, Enum.KeyCode.LeftControl)

I think you can make a variable that store the current action. Then make the "inputState == Enum.UserInputState.End" only revert walkspeed if the "action" variable from the functions is equal to the current action. Make sure to set the current action variable to nil after resetting the humanoid walkspeed.

What you need is a type of xor gate system. This should work although you need to place the script inside StarterCharacterScripts for it to work properly:

local contextActionService = game:GetService"ContextActionService"

local humanoid = script.Parent:WaitForChild"Humanoid"
local defaultWalkSpeed = humanoid.WalkSpeed

local intValue = Instance.new"IntValue"

local run, crouch = 0, 0

contextActionService:BindAction("Run", function(_, inputState)
	run = (inputState == Enum.UserInputState.Begin) and 1 or 0
	intValue.Value = run + crouch
end, false, Enum.KeyCode.LeftShift)

contextActionService:BindAction("Crouch", function(_, inputState)
	crouch = (inputState == Enum.UserInputState.Begin) and -1 or 0
	intValue.Value = run + crouch
end, false, Enum.KeyCode.LeftControl)

intValue.Changed:Connect(function(value)
	if value == 1 then -- Is running
		humanoid.WalkSpeed = defaultWalkSpeed + 5
	elseif value == -1 then -- Is crouching
		humanoid.WalkSpeed = defaultWalkSpeed - 10
	else -- Not running or crouching
		humanoid.WalkSpeed = defaultWalkSpeed
	end
end)

Edit: Actually there’s a problem but I’m working on a fix

Problem solved, this should work now:

local contextActionService = game:GetService"ContextActionService"

local humanoid = script.Parent:WaitForChild"Humanoid"
local defaultWalkSpeed = humanoid.WalkSpeed

local intValue = Instance.new"IntValue"

local run, crouch = 0, 0

contextActionService:BindAction("Run", function(_, inputState)
	run = (inputState == Enum.UserInputState.Begin) and 2 or 0
	intValue.Value = run + crouch
end, false, Enum.KeyCode.LeftShift)

contextActionService:BindAction("Crouch", function(_, inputState)
	crouch = (inputState == Enum.UserInputState.Begin) and -1 or 0
	intValue.Value = run + crouch
end, false, Enum.KeyCode.LeftControl)

intValue.Changed:Connect(function(value)
	if value == 2 then -- Is running
		humanoid.WalkSpeed = defaultWalkSpeed + 5
	elseif value == -1 then -- Is crouching
		humanoid.WalkSpeed = defaultWalkSpeed - 10
	else -- Not running or crouching
		humanoid.WalkSpeed = defaultWalkSpeed
	end
end)

Yes, this worked! Appreciate the help.

1 Like

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