I am trying to implement a wall running feature into my game but the problem is that it only works for one side of a part, for the other sides my character is flung to a different direction or completely breaks the debounce I have in my script. Here is my script and a couple of videos.
Wall Running working on one side but breaking on the other
Wall Running sending me flying to a completely different direction
local uis = game:GetService("UserInputService")
local hrp = script.Parent:FindFirstChild("HumanoidRootPart")
local humanoid = script.Parent:FindFirstChild("Humanoid")
local attachment = Instance.new("Attachment")
attachment.Parent = hrp
local db = false
local velocity
hrp.Touched:Connect(function(hit)
if uis:IsKeyDown(Enum.KeyCode.Space) then
if humanoid:GetState(Enum.HumanoidStateType.Freefall) then
if hit.Name == "wall" then
if not db then
db = true
local raycastResult = workspace:Raycast(hrp.Position, hit.Position)
local gravity = Instance.new("LinearVelocity")
gravity.Name = "gravity"
gravity.Parent = hrp
gravity.Attachment0 = attachment
if raycastResult then
if math.abs(raycastResult.Normal.Z) > math.abs(raycastResult.Normal.X) then
velocity = Vector3.new(
humanoid.MoveDirection.X * 50,
-3,
-raycastResult.Normal.Z * 1000
)
print("normal z is LESS than x")
print(raycastResult.Normal)
end
if math.abs(raycastResult.Normal.Z) < math.abs(raycastResult.Normal.X) then
velocity = Vector3.new(
-raycastResult.Normal.X * 1000,
-3,
humanoid.MoveDirection.Z * 50
)
print("normal z is MORE than x")
print(raycastResult.Normal)
end
gravity.MaxForce = 3000
gravity.VectorVelocity = velocity
repeat
wait()
until humanoid:GetState() == Enum.HumanoidStateType.Landed
gravity:Destroy()
db = false
print("db false")
end
else
print("delay")
end
end
end
end
end)
edit: here is some new code while i was trying to figure out how to fix my problem
local uis = game:GetService("UserInputService")
local hrp = script.Parent:FindFirstChild("HumanoidRootPart")
local humanoid = script.Parent:FindFirstChild("Humanoid")
local attachment = Instance.new("Attachment")
attachment.Parent = hrp
local isGrounded = script.Parent.Values.isGrounded
local function isZero(numA, numB)
local sol = numA / numB
if sol == 0 then
return numB
else
return sol
end
end
humanoid.StateChanged:Connect(function()
if humanoid:GetState() == Enum.HumanoidStateType.Freefall then
isGrounded = false
elseif humanoid:GetState() == Enum.HumanoidStateType.Landed or humanoid:GetState() == Enum.HumanoidStateType.Climbing then
isGrounded = true
end
end)
hrp.Touched:Connect(function(hit)
if not isGrounded then
if uis:IsKeyDown(Enum.KeyCode.Space) then
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Whitelist
raycastParams.FilterDescendantsInstances = {workspace.wall}
local raycastResult = workspace:Raycast(hrp.Position, hit.Position, raycastParams)
local gravity = Instance.new("LinearVelocity")
gravity.Name = "gravity"
gravity.Parent = hrp
gravity.Attachment0 = attachment
if raycastResult then
local velocity = Vector3.new(
isZero(-raycastResult.Normal.X, humanoid.MoveDirection.X), -3/50,
isZero(-raycastResult.Normal.Z, humanoid.MoveDirection.Z)
) * 50
print("wallforce "..tostring(raycastResult.Normal))
print("movedirection "..tostring(humanoid.MoveDirection))
gravity.MaxForce = 3000
gravity.VectorVelocity = velocity
print("NEWvelocity "..tostring(velocity))
wait(2)
gravity:Destroy()
end
end
end
end)
1 Like
I’m also making a wall running system and while making something similar i encountered the same problem.
So I think this could possibly help you.
--This doesn't need to check the axis
local A = Vector3.new(raycastResult.Normal.Z,0,raycastResult.Normal.X)
local RayCastDirection = (hrp.Position - hit.Position).unit
--Gets the directional Vector between the two points
local B = Vector3.new(RayCastDirection.Z,0,RaycastDirection.X)
local VelocitySpeed = 3
local Velocity = (((A * B) * script.Parent.Humanoid.WalkSpeed * Velocity) * LookVector) * -1
Velocity = Vector3.new(Velocity.X, -3, Velocity.Z)
gravity.VectorVelocity = Velocity
--Walk Speed isn't necessary, just there because my system is based off speed.
I hope this solves your problem.
unfortunately it hasn’t, i am thinking it might have to do with the math we used or a problem regarding the raycasting. thanks anyways
Ok so trying to clean up my code, I broke my script and realized what was wrong.
--RayCastDirection needs to be replaced with this
local RayCastDirection = (raycastResult.Position - hrp.Position).unit
--and also, there was a typo in this of "Velocity" instead of "VelocitySpeed"
local Velocity = (((A * B) * VelocitySpeed) * LookVector) * -1
--LookVector can be from any body part, but I use Head.CFrame.LookVector
Hopefully this finally fixes it and if not oh well, and if not it’s probably due to the difference in the way our scripts work. I would try having a jump or double jump to trigger the raycast instead of using the touched event and seeing how that works.
sorry but it still doesnt fix the problem, but i have found another solution that could help the both of us. So i have the script fire two rays from the sides of the player detecting collisions instead of a single ray pointing towards a wall’s position.
local rayL = workspace:Raycast(hrp.Position, hrp.CFrame.RightVector * -10, raycastParams)
local rayR = workspace:Raycast(hrp.Position, hrp.CFrame.RightVector * 10, raycastParams)
if rayL or rayR then
if rayL then
-- insert code if the left ray detects a collision
elseif rayR then
-- insert code if the right ray detects a collision
end
end
and as well as my full code (works with angled walls too)
local uis = game:GetService("UserInputService")
local hrp = script.Parent:FindFirstChild("HumanoidRootPart")
local humanoid = script.Parent:FindFirstChild("Humanoid")
-- Values is a folder I created in StarterCharacterScripts
local isGrounded = script.Parent:WaitForChild("Values").isGrounded
humanoid.StateChanged:Connect(function()
if humanoid:GetState() == Enum.HumanoidStateType.Freefall then
isGrounded = false
elseif humanoid:GetState() == Enum.HumanoidStateType.Landed or humanoid:GetState() == Enum.HumanoidStateType.Climbing then
isGrounded = true
end
end)
hrp.Touched:Connect(function(hit)
if isGrounded then
return
end
if uis:IsKeyDown(Enum.KeyCode.Space) and uis:IsKeyDown(Enum.KeyCode.LeftShift) then
local raycastParams = RaycastParams.new()
raycastParams.FilterType = Enum.RaycastFilterType.Blacklist
raycastParams.FilterDescendantsInstances = {script.Parent}
local attachment = Instance.new("Attachment")
attachment.Parent = hrp
local wallrunForce = Instance.new("LinearVelocity")
wallrunForce.Name = "wallrunForce"
wallrunForce.Attachment0 = attachment
local rayL = workspace:Raycast(hrp.Position, hrp.CFrame.RightVector * -10, raycastParams)
local rayR = workspace:Raycast(hrp.Position, hrp.CFrame.RightVector * 10, raycastParams)
if rayL or rayR then
local velocity
wallrunForce.Parent = hrp
-- swapped axis is intentional
if rayL then
if math.abs(rayL.Normal.Z) == 1 then
velocity = Vector3.new(rayL.Normal.Z, -3/50, rayL.Normal.X) * 50
elseif math.abs(rayL.Normal.X) == 1 then
velocity = -Vector3.new(rayL.Normal.Z, 3/50, rayL.Normal.X) * 50
else
velocity = Vector3.new(rayL.Normal.Z, -3/50, -rayL.Normal.X) * 50
end
elseif rayR then
if math.abs(rayR.Normal.Z) == 1 then
velocity = -Vector3.new(rayR.Normal.Z, 3/50, rayR.Normal.X) * 50
elseif math.abs(rayR.Normal.X) == 1 then
velocity = Vector3.new(rayR.Normal.Z, -3/50, rayR.Normal.X) * 50
else
velocity = Vector3.new(-rayR.Normal.Z, -3/50, rayR.Normal.X) * 50
end
end
wallrunForce.MaxForce = 3000
wallrunForce.VectorVelocity = velocity
end
repeat
local loopRayL = workspace:Raycast(hrp.Position, hrp.CFrame.RightVector * -10, raycastParams)
local loopRayR = workspace:Raycast(hrp.Position, hrp.CFrame.RightVector * 10, raycastParams)
wait()
until isGrounded or not uis:IsKeyDown(Enum.KeyCode.LeftShift) or not loopRayR and not loopRayL
wallrunForce:Destroy()
end
end)
2 Likes