Check If Raycast Doesn't Hit Anything

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)

Heres a video showing it:

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

I did that but it still doesn’t stop when there is no longer a wall there. Do you know why this happens?

I think you’re looking for this?

if Right.Instance == nil then
    -- the ray hit nothing
end

Vice versa for left

Edit: So change the following lines

if Right.Instance ~= nil then
	LinearVelocity.Enabled = true
	LinearVelocity.VectorVelocity = RootPart.CFrame.lookVector * Speed + Vector3.new(RootPart.AssemblyLinearVelocity.X, -5, RootPart.AssemblyLinearVelocity.Z)
end

if Left.Instance ~= nil then
	LinearVelocity.Enabled = true
	LinearVelocity.VectorVelocity = RootPart.CFrame.lookVector * Speed + Vector3.new(RootPart.AssemblyLinearVelocity.X, -5, RootPart.AssemblyLinearVelocity.Z)
end

I think raycast still returns, even if it doesn’t hit anything? Correct me if I’m wrong

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)

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.