I’m making a wall running script and everything works well, but I’m not sure how to check if a raycast doesn’t hit anything. It doesn’t seem to work when I check if the raycast is false. Heres my code:
local Speed = 50
local RaycastLength = 2.5
local Character = script.Parent
local Humanoid = Character:FindFirstChildWhichIsA("Humanoid")
local RootPart = Humanoid.RootPart
local UserInputService = game:GetService("UserInputService")
local Attachment = Instance.new("Attachment", RootPart)
local LinearVelocity = Instance.new("LinearVelocity")
LinearVelocity.Attachment0 = Attachment
LinearVelocity.Enabled = false
LinearVelocity.ForceLimitMode = Enum.ForceLimitMode.PerAxis
LinearVelocity.MaxAxesForce = Vector3.new(math.huge, 0, math.huge)
LinearVelocity.VectorVelocity = RootPart.CFrame.LookVector * Speed + RootPart.AssemblyLinearVelocity
LinearVelocity.Parent = RootPart
UserInputService.InputBegan:Connect(function(Input, Typing)
if Typing then return end
if Humanoid.FloorMaterial ~= Enum.Material.Air then return end
if Input.KeyCode == Enum.KeyCode.Space then
local Params = RaycastParams.new()
Params.FilterDescendantsInstances = {Character}
Params.FilterType = Enum.RaycastFilterType.Exclude
local Origin = RootPart.CFrame.Position
local RightDirection = RootPart.CFrame.RightVector * RaycastLength
local LeftDirection = RootPart.CFrame.RightVector * -RaycastLength
Right = workspace:Raycast(Origin, RightDirection, Params)
Left = workspace:Raycast(Origin, LeftDirection, Params)
if Right then
LinearVelocity.Enabled = true
LinearVelocity.VectorVelocity = RootPart.CFrame.lookVector * Speed + Vector3.new(RootPart.AssemblyLinearVelocity.X, -5, RootPart.AssemblyLinearVelocity.Z)
end
if Left then
LinearVelocity.Enabled = true
LinearVelocity.VectorVelocity = RootPart.CFrame.lookVector * Speed + Vector3.new(RootPart.AssemblyLinearVelocity.X, -5, RootPart.AssemblyLinearVelocity.Z)
end
end
end)
while Right == false and Left == false do
LinearVelocity.Enabled = false
task.wait(0.1)
end
UserInputService.InputEnded:Connect(function(Input, Typing)
if Typing then return end
if Input.KeyCode == Enum.KeyCode.Space then
LinearVelocity.Enabled = false
end
end)
When a raycast doesn’t hit anything it returns nil, not false. nil is not the same as false, but both are considered “falsey” inside an if statement or when using the not operator
not nil is true not false is true not workspace:Raycast() is the same as workspace:Raycast()==nil
There are different ways to do what you want:
while Right==nil and Left==nil do
while not (Right or Left) do
Nevermind I see the problem. You need to set up a while loop after the input event and cast the ray. Keep casting the ray until it doesn’t return anything, and then break the loop. The problem you have is that you aren’t actually setting Right or Left to false. The ray is only being casted once, on input
For example:
UserInputService.InputBegan:Connect(function()
-- doo all necessary stuff
while true do -- or use render stepped
local right= workspace:Raycast(Origin, RightDirection, Params)
local left = workspace:Raycast(Origin, LeftDirection, Params)
if not Right and not Left then
break
end
if Right then
-- doo stuff
end
if Left then
-- do stuff
end
task.wait(0.1)
end
Left = false; Right = false
end)
workspace:Raycast() doesn’t return a raycastresult if it hits nothing, it returns nil, so this will just error.
This while loop only runs once, once the condition is no longer true it will stop looping through. I would instead just use a renderstepped or heartbeat connection to check for your raycasts.
Also, putting everything inside of inputbegan means that your rays only update whenever an input, so if the player stops inputting anything then they can just keep the linearvelocity enabled.
Given that, heres a revised version that should work:
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local Speed = 50
local RaycastLength = 2.5
local PlayerStates = {
Wallrunning = false;
}
local Character = script.Parent
local Humanoid = Character:FindFirstChildWhichIsA("Humanoid")
local RootPart = Humanoid.RootPart
local Attachment = Instance.new("Attachment", RootPart)
local LinearVelocity = Instance.new("LinearVelocity")
LinearVelocity.Attachment0 = Attachment
LinearVelocity.Enabled = false
LinearVelocity.ForceLimitMode = Enum.ForceLimitMode.PerAxis
LinearVelocity.MaxAxesForce = Vector3.new(math.huge, 0, math.huge)
LinearVelocity.VectorVelocity = RootPart.CFrame.LookVector * Speed + RootPart.AssemblyLinearVelocity
LinearVelocity.Parent = RootPart
local LeftRaycast: RaycastResult
local RightRaycast: RaycastResult
function GetState(StateName: string)
return PlayerStates[StateName]
end
function SetState(StateName: string, State: boolean)
PlayerStates[StateName] = State
end
function OnInputBegan(Input, gameProcessed)
if gameProcessed then return end
if Humanoid.FloorMaterial ~= Enum.Material.Air then return end
if Input.KeyCode == Enum.KeyCode.Space and (LeftRaycast or RightRaycast) then
LinearVelocity.Enabled = true
LinearVelocity.VectorVelocity = RootPart.CFrame.lookVector * Speed + Vector3.new(RootPart.AssemblyLinearVelocity.X, -5, RootPart.AssemblyLinearVelocity.Z)
SetState("Wallrunning", true)
end
end
function OnInputEnded(Input, gameProcessed)
if gameProcessed then return end
if Input.KeyCode ~= Enum.KeyCode.Space then
return
end
if GetState("Wallrunning") then
LinearVelocity.Enabled = false
SetState("Wallrunning", false)
end
end
function RenderSteppedLoop()
local ExcludeCharacter = RaycastParams.new()
ExcludeCharacter.FilterDescendantsInstances = {Character}
ExcludeCharacter.FilterType = Enum.RaycastFilterType.Exclude
local Origin = RootPart.CFrame.Position
local RightDirection = RootPart.CFrame.RightVector * RaycastLength
local LeftDirection = RootPart.CFrame.RightVector * -RaycastLength
LeftRaycast = workspace:Raycast(Origin, RightDirection, ExcludeCharacter)
RightRaycast = workspace:Raycast(Origin, LeftDirection, ExcludeCharacter)
if not (LeftRaycast or RightRaycast) and GetState("Wallrunning") then
LinearVelocity.Enabled = false
SetState("Wallrunning", false)
end
end
UserInputService.InputBegan:Connect(OnInputBegan)
UserInputService.InputEnded:Connect(OnInputEnded)
RunService.RenderStepped:Connect(RenderSteppedLoop)