Player can't WallJump more than once

Hi, so i’ve made a wall-jumping system for my game. And, simply put, what it should do is checks for parts around the player within a 3 stud radius, and if it finds a part that has the “Wall Jump” tag, and the Player is close to that part and decides to jump, then it’ll allow him to jump only once in front of that part until the player lands, but still allow other parts with the “Wall Jump” tag to be jumped on. The issue is that it doesn’t allow that last part. I know it’s kinda hard to understand, but i have put a video showing the problem.

local NearWall = false
local Jumped = false
local function WallJump()
    --------------------------------------
    while Humanoid:GetState() == Enum.HumanoidStateType.Freefall do
        local Params = OverlapParams.new()
        Params.FilterType = Enum.RaycastFilterType.Exclude
        Params.FilterDescendantsInstances = {Character}
        --------------------------------------
        local Parts = workspace:GetPartBoundsInRadius(Root.Position, 1.5, Params)
        --------------------------------------
        UIS.JumpRequest:Connect(function()
            if NearWall and not Jumped then
                Jumped = true
                Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
                --------------------------------------
                if Root:FindFirstChild("WJEffect") then
                    Root.WJEffect:Destroy()
                elseif Root:FindFirstChild("WJSound") then
                    Root.WJSound:Destroy()
                end
                --------------------------------------
                local Sound = Sounds.Player.WJSound:Clone()
                Sound.Parent = Root
                Sound.PlaybackSpeed = math.random(9, 10)
                Sound:Play()
                --------------------------------------
                local Effect = Effects.Player.WJEffect:Clone()
                Effect.Parent = Root
                Effect.CFrame = Root.CFrame
                local TweenInform = TweenInfo.new(0.25, Enum.EasingStyle.Linear, Enum.EasingDirection.In)
                local TweenEffectSize = TweenService:Create(Effect.GUI.ImageLabel, TweenInform, {Size = UDim2.new(1, 0, 1, 0)})
                local TweenEffectTransparency = TweenService:Create(Effect.GUI.ImageLabel, TweenInform, {ImageTransparency = 1})
                TweenEffectSize:Play()
                TweenEffectTransparency:Play()
                --------------------------------------
                Debris:AddItem(Effect, 0.25)
                Debris:AddItem(Sound, 1)
                --------------------------------------
                repeat
                    task.wait()
                until Humanoid:GetState() == Enum.HumanoidStateType.Landed
                --------------------------------------
                Jumped = false
                NearWall = false
            else
                return
            end
        end)
        --------------------------------------
        for _, Part : Part in ipairs(Parts) do
            if Part:HasTag("Wall Jump") then
                local Distance = (Root.Position - Part.Position).Magnitude
                if Distance <= 6 then
                    NearWall = true
                    break
                else
                    NearWall = false
                end
                print(NearWall)
            end
        end
        task.wait()
    end
end

local function StateHandler(Old, New)
    if New == Enum.HumanoidStateType.Freefall then
        WallJump()
    end
end

Humanoid.StateChanged:Connect(StateHandler)

2 Likes

Hey there!

Not sure if it’ll work, but you can try changing the Jumped and NearWall to false in the StateHandler function by detecting if New = Enum.HumanoidStateType.Landed. Then you can remove the repeat task.wait() until from the connection.

I like to mess with the script like this to see if anything changes.

Hope it helps :wink:

Hi, thanks for your help! I just tried it tho, and it sadly didn’t work. :sad:

bump, plz help with this issue

I tested the code and it seems to work with multiple parts; however, I noticed that the distance is calculated from the center of mass. Perhaps the part is too far away?

1 Like


Video example of the code. The line shows when you are close enough to the wall to jump.
As of the current code, you can’t wall jump again until you touch the ground.

If you want to wall jump from one wall to the next, you will need a check and turn the value “Jumped” to false when meeting a new wall.
(I’m assuming this is your goal, if I’m reading the question correctly)

Edit: I didn’t change the original code besides removing the extra effects so the code should work the same.

Well, the Root part is set to Massless, so i don’t know if that’s true?

Thanks, that video helped me to understand better. But how would i implement the check? I tried doing this :

`if Part:HasTag("Wall Jump") then
                Jumped = false
                local Distance = (Root.Position - Part.Position).Magnitude
                if Distance <= 6 then
                    NearWall = true
                    break
                else
                    NearWall = false
                end
                print(NearWall)
            end`

and it does work and allow the player to jump on another wall, but it makes the player jump way too many times.

I’m not entirely sure why it only works once because it’s a bit difficult to read code blocks on mobile but I did find something that is definitely going to be an issue and might cause your issue.
This part will cause a memory leak

Since you never disconnect this event it will continue firing and connecting new events every time the function is called. This can cause unexpected behavior and will cause a memory leak. Make sure you disconnect it when you do not expect the event to be used again

local jumpRequest
jumpRequest = UIS.JumpRequest:Connect()

--disconnect it somewhere in the function
jumpRequest:Disconnect()
1 Like

Good thinking. That actually solved one of the issues i forgot to mention. Now, there’s still the problem about not being able to wall jump on more than one wall.

1 Like

Do you mean not being able to wall jump on any wall other than one or can you only wall jump once?

If it’s the first, check if the other walls has the Wall Jump tag and has CanQuery on.

1 Like

I believe the issue seems to be that the NearWall flag isn’t resetting properly when the player moves between walls, preventing the last wall jump from registering.

for _, Part : Part in ipairs(Parts) do
    if Part:HasTag("Wall Jump") then
        local Distance = (Root.Position - Part.Position).Magnitude
        if Distance <= 6 then
            NearWall = true
            break
        else
            NearWall = false -- # This is overriding valid wall checks
        end
    end
end

To fix this, you can do the following

for _, Part : Part in ipairs(Parts) do
    if Part:HasTag("Wall Jump") then
        local Distance = (Root.Position - Part.Position).Magnitude
        if Distance <= 6 then
            NearWall = true
            break
        end
    end
end

I mean you shouldn’t be able to wall jump on the same wall more than once, if you’re close to it. I think what i need to fix this issue once and for all is a way to detect whether or not the new Raycast detects the same wall as the previous one.

Just tried it, sadly it doesn’t seem to work. Dang this is really confusing!

If you intend to be able to wall jump on the same wall again if you did so on the other wall, you could just have a variable that stores the wall that you jumped on and have that variable be overwritten by another wall you jump onto if you get the idea.

So like instead of NearWall = true and NearWall = false, it would be Nearwall = Part and NearWall = nil

This is so that we can assign the wall we jumped on to a variable that we will call PreviousWall and check if it’s the same wall, like this:

if NearWall and NearWall ~= PreviousWall then
    Jumped = true -- I think you can remove this if you're not gonna use it.
    PreviousWall = NearWall
    Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)

And after landing, we reset the variables:

Jumped = false -- Remove if not using.
PreviousWall = nil
NearWall = nil

For the landing check, I would just move the codes above outside of the loop since the loop stops and runs the codes underneath it when we land, like this:

while Humanoid:GetState() == Enum.HumanoidStateType.Freefall do
    -- ...
end

Jumped = false -- Remove if not using.
PreviousWall = nil
NearWall = nil

So like this?

local PreviousWall = nil
local NearWall = nil
local function WallJump()
    --------------------------------------
    while Humanoid:GetState() == Enum.HumanoidStateType.Freefall do
        local Params = OverlapParams.new()
        Params.FilterType = Enum.RaycastFilterType.Exclude
        Params.FilterDescendantsInstances = {Character}
        --------------------------------------
        local Connection
        --------------------------------------
        local Parts = workspace:GetPartBoundsInRadius(Root.Position, 1.5, Params)
        --------------------------------------
        Connection = UIS.JumpRequest:Connect(function()
            if NearWall and NearWall ~= PreviousWall then
                Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
                --------------------------------------
                if Root:FindFirstChild("WJEffect") then
                    Root.WJEffect:Destroy()
                elseif Root:FindFirstChild("WJSound") then
                    Root.WJSound:Destroy()
                end
                --------------------------------------
                local Sound = Sounds.Player.WJSound:Clone()
                Sound.Parent = Root
                Sound.PlaybackSpeed = math.random(9, 10)
                Sound:Play()
                --------------------------------------
                local Effect = Effects.Player.WJEffect:Clone()
                Effect.Parent = Root
                Effect.CFrame = Root.CFrame
                local TweenInform = TweenInfo.new(0.25, Enum.EasingStyle.Linear, Enum.EasingDirection.In)
                local TweenEffectSize = TweenService:Create(Effect.GUI.ImageLabel, TweenInform, {Size = UDim2.new(1, 0, 1, 0)})
                local TweenEffectTransparency = TweenService:Create(Effect.GUI.ImageLabel, TweenInform, {ImageTransparency = 1})
                TweenEffectSize:Play()
                TweenEffectTransparency:Play()
                --------------------------------------
                Debris:AddItem(Effect, 0.25)
                Debris:AddItem(Sound, 1)
                --------------------------------------
                repeat
                    task.wait()
                until Humanoid:GetState() == Enum.HumanoidStateType.Landed
                --------------------------------------
                NearWall = nil
                PreviousWall = nil
            else
                return
            end
        end)
        --------------------------------------
        for _, Part : Part in ipairs(Parts) do
            if Part:HasTag("Wall Jump") then
                local Distance = (Root.Position - Part.Position).Magnitude
                if Distance <= 6 then
                    NearWall = Part
                    break
                else
                    NearWall = nil
                    Connection:Disconnect()
                end
            end
        end
        task.wait()
    end
end

What is thatt :sob:

Let me fix it for ya. :+1:

local PreviousWall = nil
local NearWall = nil

local function WallJump()
    local Connection = UIS.JumpRequest:Connect(function()
        if NearWall and NearWall ~= PreviousWall then
            PreviousWall = NearWall
            Humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
            --------------------------------------
            if Root:FindFirstChild("WJEffect") then
                Root.WJEffect:Destroy()
            elseif Root:FindFirstChild("WJSound") then
                Root.WJSound:Destroy()
            end
            --------------------------------------
            local Sound = Sounds.Player.WJSound:Clone()
            Sound.Parent = Root
            Sound.PlaybackSpeed = math.random(9, 10)
            Sound:Play()
            --------------------------------------
            local Effect = Effects.Player.WJEffect:Clone()
            Effect.Parent = Root
            Effect.CFrame = Root.CFrame
            local TweenInform = TweenInfo.new(0.25, Enum.EasingStyle.Linear, Enum.EasingDirection.In)
            local TweenEffectSize = TweenService:Create(Effect.GUI.ImageLabel, TweenInform, {Size = UDim2.new(1, 0, 1, 0)})
            local TweenEffectTransparency = TweenService:Create(Effect.GUI.ImageLabel, TweenInform, {ImageTransparency = 1})
            TweenEffectSize:Play()
            TweenEffectTransparency:Play()
            --------------------------------------
            Debris:AddItem(Effect, 0.25)
            Debris:AddItem(Sound, 1)
        end
    end)

    --------------------------------------
    while Humanoid:GetState() == Enum.HumanoidStateType.Freefall do
        local Params = OverlapParams.new()
        Params.FilterType = Enum.RaycastFilterType.Exclude
        Params.FilterDescendantsInstances = {Character}
        --------------------------------------
        local Parts = workspace:GetPartBoundsInRadius(Root.Position, 1.5, Params)
        --------------------------------------
        for _, Part : Part in ipairs(Parts) do
            if Part:HasTag("Wall Jump") then
                local Distance = (Root.Position - Part.Position).Magnitude
                if Distance <= 6 then
                    NearWall = Part
                    break
                else
                    NearWall = nil
                end
            end
        end
        task.wait()
    end
    --------------------------------------
    Connection:Disconnect()

    NearWall = nil
    PreviousWall = nil
end
1 Like

Oof :skull:
It still won’t work sadly

Does the problem still persist or did you get a new problem?

If the problem still persists, make sure that other walls have Wall Jump tag and CanQuery enabled in their properties. CanQuery is enabled by default when CanCollide is enabled.

This is what happens:


And yes, the walls do have Wall Jump tag and CanQuery