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:
(casted midair, player is on the ground.)
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).
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.
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!