Wallclimb issue, please help

My issue is when I let go of space early/before the wallclimbing ends I can’t wallclimb a second time, but if I let it finish I can.

video:

local script:

local c = script.Parent
local holdingKey = false
local wallrunCount = 1
local wallrunDuration = 1
local wallrunTimer = 0
local maxWallruns = 2
local fallThreshold = 3
local canWallclimb = true

local UIS = game:GetService("UserInputService")
local ClimbAnim = c.Humanoid:LoadAnimation(script:WaitForChild("ClimbAnim"))
local WallClimbSound = game.ReplicatedStorage.Sounds.WallclimbSound

local plr = game.Players.LocalPlayer
local char = plr.Character
local hum = char:WaitForChild("Humanoid")

local initialWalkSpeed = 0
local targetWalkSpeed = 10
local accelerationRate = (targetWalkSpeed - initialWalkSpeed) / wallrunDuration
local originalWalkSpeed = c.Humanoid.WalkSpeed

plr:SetAttribute("WallClimbing", false)

UIS.InputBegan:Connect(function(input, gameProcessedEvent)
	if gameProcessedEvent then return end
	if input.KeyCode == Enum.KeyCode.Space then
		if not holdingKey and canWallclimb and wallrunCount < maxWallruns then
			holdingKey = true

			
			wallrunTimer = 0
			canWallclimb = false


			
			originalWalkSpeed = c.Humanoid.WalkSpeed
		end
	end
end)

UIS.InputEnded:Connect(function(input, gameProcessedEvent)
	if gameProcessedEvent then return end
	if input.KeyCode == Enum.KeyCode.Space then
		holdingKey = false
	end
end)

UIS.InputBegan:Connect(function(input, gameProcessedEvent)
	if gameProcessedEvent and (input.KeyCode ~= Enum.KeyCode.ButtonA) then return end

	if input.UserInputType == Enum.UserInputType.Gamepad1 then
		if input.KeyCode == Enum.KeyCode.ButtonA then
			if not holdingKey and canWallclimb and wallrunCount < maxWallruns then
				holdingKey = true

				
				wallrunTimer = 0
				canWallclimb = false


				
				originalWalkSpeed = c.Humanoid.WalkSpeed
			end
		end
	end
end)

UIS.InputEnded:Connect(function(input, gameProcessedEvent)
	if gameProcessedEvent and (input.KeyCode ~= Enum.KeyCode.ButtonA) then return end

	if input.UserInputType == Enum.UserInputType.Gamepad1 then
		if input.KeyCode == Enum.KeyCode.ButtonA then
			holdingKey = false
		end
	end
end)

game:GetService("RunService").Heartbeat:Connect(function(deltaTime)
	local raycastParams = RaycastParams.new()
	raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
	raycastParams.FilterDescendantsInstances = {c}
	raycastParams.IgnoreWater = true

	local rayUp = workspace:Raycast(c.HumanoidRootPart.Position, c.HumanoidRootPart.CFrame.LookVector * 3, raycastParams)
	local rayDown = workspace:Raycast(c.HumanoidRootPart.Position, -c.HumanoidRootPart.CFrame.UpVector * fallThreshold, raycastParams)
	local ray = rayUp

	if rayDown and not ray and not canWallclimb then
		canWallclimb = true
	end

	if ray and holdingKey and not canWallclimb then
		if not ClimbAnim.IsPlaying then
			ClimbAnim:Play()
			plr:SetAttribute("WallClimbing", true)
		end

		local currentWalkSpeed = c.Humanoid.WalkSpeed
		if currentWalkSpeed < targetWalkSpeed then
			currentWalkSpeed = math.min(currentWalkSpeed + accelerationRate * deltaTime, targetWalkSpeed)
			c.Humanoid.WalkSpeed = currentWalkSpeed
		end

		wallrunTimer = wallrunTimer + deltaTime

		local part = ray.Instance

		local weld = c.HumanoidRootPart:FindFirstChild("WallrunWeld") or Instance.new("WeldConstraint")
		weld.Name = "WallrunWeld"
		weld.Part0 = c.HumanoidRootPart
		weld.Part1 = part

		local bp = c.HumanoidRootPart:FindFirstChild("WallrunBodyPosition") or Instance.new("BodyPosition", c.HumanoidRootPart)
		bp.Name = "WallrunBodyPosition"
		bp.MaxForce = Vector3.new(math.huge, math.huge, math.huge)
		bp.Position = c.HumanoidRootPart.Position + c.HumanoidRootPart.CFrame.UpVector * c.Humanoid.WalkSpeed / 3

		if wallrunTimer >= wallrunDuration then
			holdingKey = false
			wallrunCount = wallrunCount + 1
			if wallrunCount >= maxWallruns then
				wallrunCount = 0
				canWallclimb = true
			end
		end

		if not WallClimbSound.IsPlaying then
			WallClimbSound:Play()
		end
	else
		for i, child in pairs(c.HumanoidRootPart:GetChildren()) do
			if child.Name == "WallrunWeld" or child.Name == "WallrunBodyPosition" then
				c.Humanoid.WalkSpeed = originalWalkSpeed
				child:Destroy()
			end
		end
		
		plr:SetAttribute("WallClimbing", false)
		ClimbAnim:Stop()
		wallrunTimer = 0

		if WallClimbSound.IsPlaying then
			WallClimbSound:Stop()
		end
	end
end)

Seems like a lot of trouble to climb … could just add an invisible TrussParts part in the wall.
Don’t know what you’re all doing so here is a script, I hope it works out.

Script
local c = script.Parent
local holdingKey = false
local wallrunCount = 1
local wallrunDuration = 1
local wallrunTimer = 0
local maxWallruns = 2
local fallThreshold = 3
local canWallclimb = true

local UIS = game:GetService("UserInputService")
local ClimbAnim = c.Humanoid:LoadAnimation(script:WaitForChild("ClimbAnim"))
local WallClimbSound = game.ReplicatedStorage.Sounds.WallclimbSound

local plr = game.Players.LocalPlayer
local char = plr.Character
local hum = char:WaitForChild("Humanoid")

local initialWalkSpeed = 0
local targetWalkSpeed = 10
local accelerationRate = (targetWalkSpeed - initialWalkSpeed) / wallrunDuration
local originalWalkSpeed = c.Humanoid.WalkSpeed

plr:SetAttribute("WallClimbing", false)

UIS.InputBegan:Connect(function(input, gameProcessedEvent)
	if gameProcessedEvent or holdingKey or not canWallclimb or wallrunCount >= maxWallruns then return end
	if input.KeyCode == Enum.KeyCode.Space or (input.KeyCode == Enum.KeyCode.ButtonA and input.UserInputType == Enum.UserInputType.Gamepad1) then
		holdingKey = true
		wallrunTimer = 0
		canWallclimb = false
		originalWalkSpeed = c.Humanoid.WalkSpeed
	end
end)

UIS.InputEnded:Connect(function(input, gameProcessedEvent)
	if gameProcessedEvent or not holdingKey then return end
	if input.KeyCode == Enum.KeyCode.Space or (input.KeyCode == Enum.KeyCode.ButtonA and input.UserInputType == Enum.UserInputType.Gamepad1) then
		holdingKey = false
	end
end)

game:GetService("RunService").Heartbeat:Connect(function(deltaTime)
	local raycastParams = RaycastParams.new()
	raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
	raycastParams.FilterDescendantsInstances = {c}
	raycastParams.IgnoreWater = true

	local rayUp = workspace:Raycast(c.HumanoidRootPart.Position, c.HumanoidRootPart.CFrame.LookVector * 3, raycastParams)
	local rayDown = workspace:Raycast(c.HumanoidRootPart.Position, -c.HumanoidRootPart.CFrame.UpVector * fallThreshold, raycastParams)
	local ray = rayUp

	if rayDown and not ray and not canWallclimb then
		canWallclimb = true
	end

	if ray and holdingKey and not canWallclimb then
		if not ClimbAnim.IsPlaying then
			ClimbAnim:Play()
			plr:SetAttribute("WallClimbing", true)
		end

		local currentWalkSpeed = c.Humanoid.WalkSpeed
		if currentWalkSpeed < targetWalkSpeed then
			currentWalkSpeed = math.min(currentWalkSpeed + accelerationRate * deltaTime, targetWalkSpeed)
			c.Humanoid.WalkSpeed = currentWalkSpeed
		end

		wallrunTimer = wallrunTimer + deltaTime

		local part = ray.Instance

		local weld = c.HumanoidRootPart:FindFirstChild("WallrunWeld") or Instance.new("WeldConstraint")
		weld.Name = "WallrunWeld"
		weld.Part0 = c.HumanoidRootPart
		weld.Part1 = part

		local bp = c.HumanoidRootPart:FindFirstChild("WallrunBodyPosition") or Instance.new("BodyPosition", c.HumanoidRootPart)
		bp.Name = "WallrunBodyPosition"
		bp.MaxForce = Vector3.new(math.huge, math.huge, math.huge)
		bp.Position = c.HumanoidRootPart.Position + c.HumanoidRootPart.CFrame.UpVector * c.Humanoid.WalkSpeed / 3

		if wallrunTimer >= wallrunDuration then
			holdingKey = false
			wallrunCount = wallrunCount + 1
			if wallrunCount >= maxWallruns then
				wallrunCount = 0
				canWallclimb = true
			end
		end

		if not WallClimbSound.IsPlaying then
			WallClimbSound:Play()
		end
	else
		for i, child in pairs(c.HumanoidRootPart:GetChildren()) do
			if child.Name == "WallrunWeld" or child.Name == "WallrunBodyPosition" then
				c.Humanoid.WalkSpeed = originalWalkSpeed
				child:Destroy()
			end
		end
		
		plr:SetAttribute("WallClimbing", false)
		ClimbAnim:Stop()
		wallrunTimer = 0

		if WallClimbSound.IsPlaying then
			WallClimbSound:Stop()
		end
	end
end)

just cleaned it up … untested.

3 Likes

Ok so there’s a few things to digest here, your lack of comments makes your script quite hard to follow/understand what different t variables and conditions mean, I’d recommend going through and commenting each line where you think it’d be important to know what’s going on.

Secondly your use of the variable canWallClimb is quite confusing to me. It seems like your using the false value to tell the script that you wanna climb instead of vice versa. Evident in the condition “and not canWallClimb” then… Wall climb function. So have another look at that because there’s a good chance you might have messed up with how this might be set.

There seems to be a lot of instances in your code that are counterintuitive. You have a condition to check if the wall is within 3 studs Infront of the HRP yet you set canWallClimb to true if this condition is not met.

I think you’d be best to go through your code and clean it up a bit to help in your debugging process, also use prints to find out where it’s going wrong.