How do I filter and use the results of my raycast in a for loop?

What is my goal?
I’m working on making a wallbounce system so the player can choose to bounce off of walls for extra speed. To do this, I know I need the surface normal of the part the player tries to bounce off of, and I know I need to use rays.

The Issue
Accounting for optimization and simplicity, I’m not sure what I should do.
I want this to be as efficient as possible, but spherecasts dont work because they dont detect intersections present at initialization, and doing a 360 raycast seems a little performance heavy. Anyway, I’m doing this assuming its the most efficient way but any other ideas would be greatly appreciated.
How can I grab the surface normal of the shortest raycast inside of this for loop and return it?

local function WallJumpRayCast()

	--//raycast creation//
	local rayParams = RaycastParams.new()
	rayParams.FilterDescendantsInstances = {player.Character, ignoreList}
	rayParams.FilterType = Enum.RaycastFilterType.Exclude
	for deg = 1, 360, 45 do
		local x = 2 * math.cos(math.rad(deg))
		local z = 2 * math.sin(math.rad(deg))
		local vecDir = Vector3.new(x, 0, z)
		wallbounceRayResult = workspace:Raycast(rootPart.Position, vecDir, rayParams)
	end
	
	if wallbounceRayResult then
		print(wallbounceRayResult.Instance)
	end
	--return wallbounceRayResult.Normal -- this doesnt work.

end

this casts my rays correctly like this:
image
(casted midair, player is on the ground.)

any help would be amazing, thanks! :happy3:

You can store every result in a table and then sort the table by ascending length of ray.

local function WallJumpRayCast()

	--//raycast creation//
	local rayParams = RaycastParams.new()
	rayParams.FilterDescendantsInstances = {player.Character, ignoreList}
	rayParams.FilterType = Enum.RaycastFilterType.Exclude

	local rayResults = {}

	for deg = 1, 360, 45 do
		local x = 2 * math.cos(math.rad(deg))
		local z = 2 * math.sin(math.rad(deg))
		local vecDir = Vector3.new(x, 0, z)
		local wallbounceRayResult = workspace:Raycast(rootPart.Position, vecDir, rayParams)
		if wallbounceRayResult then
			table.insert(rayResults, wallbounceRayResult)
		end
	end
	
	if #rayResults == 0 then return end --returns nil if no ray intersected with anything

	table.sort(rayResults, function(a,b) return a.Distance < b.Distance end)

	return rayResults[1].Normal
end

Since you’re not going to be walljumping every frame, 8 raycasts seems more than reasonable for me (you could even go a little higher if your maps require this sort of accuracy).

1 Like

Raycasts are incredibly efficient and pretty much never cause performance issues; you can raycast thousands of times a frame and be perfectly fine as long as the rays are relatively short.

You can slightly optimize the script by defining the RaycastParams outside the function instead of creating a new one every time it’s called.

2 Likes

Cool! I havent done too much with tables in general and this is a great introduction for me,
This works great. I suppose if I run into any accuracy problems I’ll definitely increase the amount of rays, as well.
Thanks!

1 Like

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