I’ve been making a parkour system, mainly for testing, and I’ve found a problem. Everything was working fine, but after I added in a wall run script, the wall climb, ledge climb, and vault all broke kind of.
Here is a video of what is broken:
(I apologize about the odd formatting)
Here are all of the scripts:
LedgeClimb Local Script:
local plr = game.Players.LocalPlayer
local Character = plr.Character or plr.CharacterAdded:Wait()
local Root = Character:WaitForChild("HumanoidRootPart")
local Head = Character:WaitForChild("Head")
local Hum = Character:WaitForChild("Humanoid")
local CA = Hum:LoadAnimation(script:WaitForChild("ClimbAnim"))
local HA = Hum:LoadAnimation(script:WaitForChild("HoldAnim"))
local TouchGui = plr:WaitForChild("PlayerGui"):FindFirstChild("TouchGui")
local UIS = game:GetService("UserInputService")
ledgeavailable = true
holding = false
while game:GetService("RunService").Heartbeat:Wait() do
local r = Ray.new(Head.CFrame.p, Head.CFrame.LookVector * 5)
local part,position = workspace:FindPartOnRay(r,Character)
if part and ledgeavailable and not holding then
if part.Parent.Name ~= "vaultableObjects" and part.Parent.Name ~= "Climbable" and part.Parent.Name ~= "RUNIT" then
if part.Parent.Name =="Ledges" then
if part.Size.Y >= 7 then
if Head.Position.Y >= (part.Position.Y + (part.Size.Y / 2)) - 1 and Head.Position.Y <= part.Position.Y + (part.Size.Y / 2) and Hum.FloorMaterial == Enum.Material.Air and Root.Velocity.Y <= 0 then
Root.Anchored = true holding = true HA:Play() ledgeavailable = false
end
end
end
function climb()
local Vele = Instance.new("BodyVelocity",Root)
Root.Anchored = false
Vele.MaxForce = Vector3.new(1,1,1) * math.huge
Vele.Velocity = Root.CFrame.LookVector * 10 + Vector3.new(0,30,0)
HA:Stop() CA:Play()
game.Debris:AddItem(Vele,.15)
holding = false
wait(.75)
ledgeavailable = true
end
UIS.InputBegan:Connect(function(Key,Chat)
if not holding then return end
if Key.KeyCode == Enum.KeyCode.Space and not Chat then
climb()
end
end)
if TouchGui then
TouchGui:WaitForChild("TouchControlFrame"):WaitForChild("JumpButton").MouseButton1Click:Connect(function()
if not holding then return end climb()
end)
end
end
end
end
Vault Local Script:
local plr = game:GetService("Players").LocalPlayer
local char = plr.Character or plr.CharacterAdded:Wait()
local HRP = char:WaitForChild("HumanoidRootPart")
local Hum = char:WaitForChild("Humanoid")
local CA = Hum:LoadAnimation(script:WaitForChild("ClimbAnim"))
local vaultavail = true
while game:GetService("RunService").RenderStepped:Wait() do
local r = Ray.new(HRP.Position, HRP.CFrame.LookVector * 7 + HRP.CFrame.UpVector * -5)
local part = workspace:FindPartOnRay(r,char)
if part and vaultavail then
if part.Name ~= "Baseplate" then
if part.Name ~= "SpawnLocation" then
if part.Parent.Name ~= "Climbable" and part.Parent.Name ~= "Ledges" and part.Parent.Name ~= "RUNIT" then
if part.Parent.Name == "vaultableObjects" then
if Hum.FloorMaterial ~= Enum.Material.Air then
vaultavail = false
local Vel = Instance.new("BodyVelocity")
Vel.Parent = HRP
Vel.Velocity = Vector3.new(0,0,0)
Vel.MaxForce = Vector3.new(1,1,1) * math.huge
Vel.Velocity = HRP.CFrame.LookVector * 20 + Vector3.new(0,30,0)
CA:Play()
game.Debris:AddItem(Vel, .15)
wait(0.75)
vaultavail = true
end
end
end
end
end
end
end
WallClimb Local Script
local UIS = game:GetService("UserInputService")
local plr = game.Players.LocalPlayer
local Char = plr.Character or plr.CharacterAdded:Wait()
local HRP = Char:WaitForChild("HumanoidRootPart")
local Hum = Char:WaitForChild("Humanoid")
local Head = Char:WaitForChild("Head")
local HittingWall = false
local OnWall = false
local climbing = false
local Normal
local Pos
local Wall
local previousWall
function upclimb()
if HittingWall == true then
HRP.Velocity = Vector3.new(0,0,0)
HRP.Anchored = false
if OnWall then
if playAnim then
playAnim:Stop()
end
local bv = HRP:FindFirstChild('BV')
bv.Velocity = HRP.CFrame.LookVector * 0 + Vector3.new(0, 12.5, 0)
local animation = Instance.new("Animation")
animation.AnimationId = 'rbxassetid://7747483051'
local playAnim = Char.Humanoid:LoadAnimation(animation)
playAnim:Play()
end
end
end
function downclimb()
if HittingWall == true then
HRP.Velocity = Vector3.new(0,0,0)
HRP.Anchored = false
if OnWall then
if playAnim then
playAnim:Stop()
end
local bv = HRP:FindFirstChild('BV')
bv.Velocity = HRP.CFrame.LookVector * 0 + Vector3.new(0, -12.5, 0)
local animation = Instance.new("Animation")
animation.AnimationId = 'rbxassetid://7747483051'
local playAnim = Char.Humanoid:LoadAnimation(animation)
playAnim:Play()
end
end
end
function upclimboff()
HRP.Anchored = true
if playAnim then
playAnim:Stop()
end
local bv = HRP:FindFirstChild('BV')
bv.Velocity = HRP.CFrame.LookVector * 0 + Vector3.new(0, bv.Velocity.Y - 12.5, 0)
end
function downclimboff()
HRP.Anchored = true
if playAnim then
playAnim:Stop()
end
local bv = HRP:FindFirstChild('BV')
bv.Velocity = HRP.CFrame.LookVector * 0 + Vector3.new(0, bv.Velocity.Y + 12.5, 0)
end
spawn(function()
while game:GetService('RunService').RenderStepped:Wait() do
local r = Ray.new(Head.CFrame.p,Head.CFrame.LookVector * 5)
local hit, pos, normal = workspace:FindPartOnRay(r,Char)
if hit then
if hit.Parent.Name ~= "Ledges" and hit.Parent.Name ~= "RUNIT" and hit.Parent.Name ~= "vaultableObjects" then
if hit.Parent.Name == "Climbable" then
HittingWall = true
if playAnim then
playAnim:Stop()
end
Pos = Pos
Normal = normal
Wall = hit
previousWall = hit
end
end
end
if not hit then
if HRP:FindFirstChild("BV") and OnWall then
local bv = HRP:FindFirstChild("BV")
bv.Velocity = Vector3.new(0,0,0)
bv.Velocity = HRP.CFrame.lookVector * 10 + Vector3.new(0,40,0)
game.Debris:AddItem(bv,.15)
OnWall = false
Hum.AutoRotate = true
Hum.PlatformStand = false
elseif HRP:FindFirstChild("BV") == nil and OnWall then
local bv = Instance.new("BodyVelocity",HRP)
bv.MaxForce = Vector3.new(1,1,1) * math.huge
bv.Velocity = HRP.CFrame.LookVector * 10 + Vector3.new(0,40,0)
game.Debris:AddItem(bv,.15)
OnWall = false
Hum.AutoRotate = true
Hum.PlatformStand = false
end
Pos = nil
normal = nil
end
wait()
end
end)
UIS.InputBegan:Connect(function(Key,Chat)
if Key.KeyCode == Enum.KeyCode.Space then
climbing = not climbing
if HittingWall then
if climbing == true then
OnWall = true
HRP.CFrame = CFrame.new(HRP.CFrame.p,Vector3.new(HRP.Position.X - Normal.x,HRP.Position.Y,HRP.Position.Z - Normal.z))
local bv = Instance.new("BodyVelocity",HRP)
bv.MaxForce = Vector3.new(1,1,1) * math.huge
bv.Velocity = HRP.CFrame.LookVector * 0
bv.Name = "BV"
Char.Humanoid.AutoRotate = false
Char.Humanoid.PlatformStand = true
else
HRP:FindFirstChild("BV"):Destroy()
Char.Humanoid.AutoRotate = true
Char.Humanoid.PlatformStand = false
OnWall = false
end
end
elseif Key.KeyCode == Enum.KeyCode.W and not Chat then
upclimb()
elseif Key.KeyCode == Enum.KeyCode.S and not Chat then
downclimb()
end
end)
UIS.InputEnded:Connect(function(Key,Chat)
if Key.KeyCode == Enum.KeyCode.W and not Chat and OnWall then
upclimboff()
elseif Key.KeyCode == Enum.KeyCode.S and not Chat and OnWall then
downclimboff()
end
end)
Finally, the infamous Wall Run local script:
local char = game:GetService("Players").LocalPlayer.Character or game:GetService("Players").LocalPlayer.CharacterAdded:Wait()
local humRP = char:WaitForChild("HumanoidRootPart")
local Hum = char:WaitForChild("Humanoid")
local ava = true
local has = false
local hold = false
local left = false
local right = false
local leftplaying = false
local rightplaying = false
local LA = Hum:LoadAnimation(script:WaitForChild("RunAnim"))
local RA = Hum:LoadAnimation(script:WaitForChild("RunRightAnim"))
local Vel = Instance.new("BodyVelocity", humRP)
local BGO = Instance.new("BodyGyro")
BGO.D = 100
BGO.P = 10000
BGO.MaxTorque = Vector3.new(0,0,0)
BGO.Name = "Rot"
Vel.MaxForce = Vector3.new(0,0,0)
Vel.Name = "Vel"
function render()
local r = Ray.new(humRP.CFrame.p, humRP.CFrame.rightVector * -3)
local r2 = Ray.new(humRP.CFrame.p, humRP.CFrame.rightVector * 3)
local part,position,normal = workspace:FindPartOnRayWithIgnoreList(r, {char})
local part2,position2,normal2 = workspace:FindPartOnRayWithIgnoreList(r, {char})
local cross = Vector3.new(0,1,0):Cross(normal)
local cross2 = Vector3.new(0,1,0):Cross(normal2)
if (part and ava) or (part2 and ava) then
if (part and part.Parent.Name == "RUNIT") or (part2 and part2.Parent.Name == "RUNIT") then
if part then
humRP.CFrame = CFrame.new(humRP.CFrame.p, Vector3.new(humRP.Position.X + cross.x, humRP.Position.Y, humRP.Position.Z + cross.Z))
elseif part2 then
humRP.CFrame = CFrame.new(humRP.CFrame.p, Vector3.new(humRP.Position.X - cross2.x, humRP.Position.Y, humRP.Position.Z - cross2.Z))
end
has = true
hold = true
if hold then
BGO.CFrame = humRP.CFrame
BGO.MaxTorque = Vector3.new(1,1,1) * math.huge
Vel.MaxForce = Vector3.new(1,1,1) * math.huge
hold = false
if part then
Vel.Velocity = cross * 50
left = true
else if part2 then
Vel.Velocity = -cross2 * 50
right = true
end
end
end
end
elseif (ava and not part and not part2 and has and not hold) then
BGO.MaxTorque = Vector3.new(0,0,0)
Vel.MaxForce = Vector3.new(0,0,0)
ava = false
left = false
right = false
LA:Stop() RA:Stop()
if has then
wait(0.5)
ava = true
has = false
end
end
if left and not leftplaying then
LA:Play() leftplaying = true
elseif not left then
LA:Stop() leftplaying = false
end
if right and not rightplaying then
RA:Play() rightplaying = true
elseif not left then
RA:Stop() rightplaying = false
end
end
game:GetService("RunService").RenderStepped:Connect(function()
render()
end)
Here is an image of it all in the explorer, the parts are organized in folders, so that if I need to add another part I can just put it into one of the folders, and the mechanics for the folder will work on it: