Multiple Raycasts at once from same function?

Hey,

I use Gravity Controller and have added a script so that if a player is jumping and presses space, it will Raycast and if it hits, it moves the player to that location.

Here is the script in action:
https://gyazo.com/3d29b9bde1b6e2f329b7edf4138567c0

I am making this post because I want to slightly change this function so that it Raycasts in multiple directions.

It currently cast the ray from the HRP LookVector. I want it to be cast from the UpVector, LookVector, and -UpVector.

However, I have little experience with RayCasting and am not even sure if this is possible.

If someone could get me moving on the right track, then that will be good enough help!

Here is the code I currently use:

function latch()														-- A new latch function should be made and raycast should happen in multiple directions
																		-- and used for flying
	local origin = HRP.Position
	local direction = HRP.CFrame.LookVector * REACH						-- Side note this could be used and constantly played during the dash?

	local result = Workspace:Raycast(origin, direction, rayParams)
	if not result then return end

	latchingToWall = result.Normal
	wait(0.3)
	latchingToWall = nil
end
3 Likes

If I understand correctly, you want three raycasts going in the same direction, stacked on top of each other?

Just call Raycast again. Move the origin around and keep the direction the same.

1 Like

Well actually more like this, around the player
image

I want one going forward, one going up and one going down; if needed one at an up diagonal and one at a down diagonal.

You mean like at a 45 degree angle?

You could rotate your direction vector, that’s probably the simplest way.

local rotatedUpwards45Direction = CFrame.Angles(math.rad(-45), 0, 0) * direction

(Maybe +45 is upwards idk)

You can use that rotated direction for your raycast. Change the -45 to 45 to rotate it the other way.

Edit:

If you really are just asking how to get a direction upwards, you just use Vector3.new(0, REACH, 0) as your raycast direction.

1 Like

Well I am actually asking if it is possible to Raycast in all directions at once?

Up, down, straight, 45. -45.

Is it possible to cast a ray at all of these points, and then return the first hit, and use that for the rest of the function?

Sure. Raycast multiple times from the same origin. Store the hit positions of any that hit. Figure out which of those is closest to the origin. Use that one.

1 Like

Honestly I am very new to scripting and have only been working on it for a month.

So I am not sure how to raycast multiple times and store the hits.

I would know how to figure out which is closest and use it, but getting to that point is something I have never done before.

I messed around with the function last night and was able to figure out a way of doing what I want but I am not sure if there are any downsides to it, so I would prefer going with your method.

Summary
local results											-- Need to figure out how to instantly rotate the player to results(), or maybe just teleport them to the results?

function latching()
	
	print(results)
	latchingToWall = results
	wait(0.2)
	latchingToWall = nil
	results = nil
	
end

function upward()
	local origin = HRP.Position
	local direction = HRP.CFrame.UpVector * REACH
	
	local result = Workspace:Raycast(origin, direction, rayParams)
	if result then
		results = result.Normal
	end
	if not result then return end
end

function latch()														-- A new latch function should be made and raycast should happen in multiple directions
																		-- and used for flying
	local origin = HRP.Position
	local direction = HRP.CFrame.LookVector * REACH						-- Side note this could be used and constantly played during the dash?

	local result = Workspace:Raycast(origin, direction, rayParams)
	if result then
		results = result.Normal
	end
	
	if results == nil then
		print("results nil next raycast")
		
		upward()
		
		if results ~= nil then
			print("latching began")
			latching()
		end
	end
	
	if results ~= nil then
		print("latching began")
		latching()
	end
end

Ah I see. You basically just do one raycast after another, and check if the current one is closer than the last one.

Here, I packaged it into a function for you. I left comments that explain what it does. If you have any questions just ask!

-- raycasts from one origin in multiple directions
-- parameters:
--  
--  origin: Vector3				the origin of all the rays
--  directions: Array<Vector3>	a list of all the directions
--  rayParams: RaycastParams	the parameters for each raycast (optional)
local function MultiRaycast(origin, directions, rayParams)
	local finalResult = nil
	local finalDistanceToOrigin = nil

	-- for each of the directions passed in,
	for _, dir in directions do
		-- do a new raycast
		local result = workspace:Raycast(origin, dir, rayParams)

		if result then
			if finalResult then
				-- check the distance of this raycast's hit
				local distanceToOrigin = (result.Position - origin).Magnitude
				if (distanceToOrigin < finalDistanceToOrigin) then
					-- and if its the closest one yet, replace finalResult
					-- with this one
					finalResult = result
					finalDistanceToOrigin = distanceToOrigin
				end
			else
				-- this is the first raycast that hit something
				finalResult = result
			end
		end
	end

	return finalResult
end

You just it instead of Workspace:Raycast with a table of directions like this:

local origin = HRP.Position
local directions = {
  HRPCFrame.LookVector * REACH,
  Vector3.new(0, REACH, 0),
  Vector3.new(0, -REACH, 0)
  -- ...any other directions you want to check
}

local result = MultiRaycast(origin, directions)
if result then
  -- do whatever
end
5 Likes