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)
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.
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?
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.
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()
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.
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.
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
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
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
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.