How can I cast rays in multiple directions

Hello,

I have no code. But what im asking is how can I cast rays in multiple directions.

What I am trying to make is when if a player hits another player with the sword on the character then it does extra damage. And when not aiming on the otherplayers character then it would just do the standard damage.

Now to make this more understandable this is what i’m trying to do.

Red is the line that hits the player directly (forgot to mention that the green ons have smaller distance and the red one can hit the player from a farther distance)

And green is are the lines that have a smaller reach and deal less damage.

Hope you can help me with that

Oh and well I do have some code but that is just one raycast

Serverscript inside the sword:

local event = script.Parent:WaitForChild("fightRemote")
local event2 = script.Parent:WaitForChild("fightRemote").showDamageRemote


event.OnServerEvent:Connect(function(player)
	local char = player.Character or player.CharacterAdded:Wait()
	local humanoid = char:WaitForChild("Humanoid")
	
	local params = RaycastParams.new()
	params.FilterType = Enum.RaycastFilterType.Exclude
	params.FilterDescendantsInstances = {char}
	
	local origin = char:WaitForChild("HumanoidRootPart").Position
	local direction = char:WaitForChild("HumanoidRootPart").CFrame.LookVector * 20
	local result = workspace:Raycast(origin, direction, params)
	
	if result then
		
		local damage = 35
		local part = result.Instance
		
		local enemy = part.Parent:FindFirstChild("Humanoid") or part.Parent.Parent:FindFirstChild("Humanoid")
		
		if enemy and enemy:GetState() ~= Enum.HumanoidStateType.Dead then
			event2:FireClient(player, enemy.Parent)
			enemy:TakeDamage(damage)
		end
	end
end)

And one more thing its not neccesary but it would be cool if you’d told me how to do that aswell which is making the rays visible. Again I know how to make 1`ray visible

1 Like

Somebody please help please!!!

There’s a lot of missing information here, in what pattern do you want the rays to be fired? Conical? Spherical? The easiest solution is to just get a function that samples you a uniformly distributed Vector3 direction, i.e Random:NextUnitVector, but I doubt that’s what you want judging from your diagram.

I want it to be fired spherical

You want a script that fire the rays like this ?


Not sure what will happen to the performance though

Yes but then only on 180 degrees not 360. Do you know a way to increase performance or should I just use a sphere object and use .Touched event

It’s much better to use workspace:SphereCast() rather than multiple rays, which works in the same was as linear raycasts, but uses 3d geometry (in this case, as sphere) instead of a straight line. If you want it to be only 180 degrees, you can also use a meshPart with a hemisphere shape and rely on .Touched events. I would recommend this last method because this way it’s possible to detect multiple players if they’re near.

2 Likes

Okay ill use that for my sword then. Thanks!

Sorry that this is late, but this is the most ideal and customizable way to go around this that I can think of.

This should work as you wanted. (Sorry for minimal notetaking)

Code
--!strict

local MaxRange = 20
local MaxAngle = 180

local PrimaryPart = script.Parent --Idealy the character's root part

--Adjust params freely
local RadiusParams = OverlapParams.new()
RadiusParams.MaxParts = 0 --0 means no limit
RadiusParams.RespectCanCollide = false

--Blacklist PrimaryPart from showing in results
RadiusParams.FilterType = Enum.RaycastFilterType.Exclude
RadiusParams.FilterDescendantsInstances = {PrimaryPart}

--Adjust params freely
local RayParams = RaycastParams.new()
RayParams.RespectCanCollide = false

local function GetPosition(inst:PVInstance)
	return inst:GetPivot().Position
end

local function GetPartsInRange(From:Vector3, Range:number):{BasePart}
	local PartsInRange = workspace:GetPartBoundsInRadius(From, Range, RadiusParams)
	local Parts = {}

	for _, inst in PartsInRange do
		if inst:IsA("BasePart") then
			table.insert(Parts, inst)
		end
	end

	return Parts
end

local function GetCharactersInRange(From:Vector3, Range:number):{Model}
	local PartsInRange = workspace:GetPartBoundsInRadius(From, Range, RadiusParams)
	local Characters = {}
	
	for _, inst in PartsInRange do
		local Char = inst.Parent
		
		if Char and Char:IsA("Model") and Char:FindFirstChildOfClass("Humanoid") then
			local CharAlreadyListed = table.find(Characters, Char) ~= nil
			
			--Only add the character if it hasn't been added yet
			if not CharAlreadyListed then
				table.insert(Characters, Char)
			end
		end
	end
	
	return Characters
end

local function GetInAngle(From:Vector3, Instances:{BasePart|Model})
	local FinalInstances = {}
	
	for _, inst in Instances do
		local Position = GetPosition(inst)
		--Negate and offset the dot product
		local RelativeAngleDot = -PrimaryPart.CFrame.LookVector:Dot(CFrame.lookAt(From, Position).LookVector)
		RelativeAngleDot += 1
		
		if (RelativeAngleDot * 180) <= MaxAngle then
			table.insert(FinalInstances, inst)
		end
	end
	
	return FinalInstances
end

while task.wait(1.5) do
	local PrimaryPos = PrimaryPart.Position
	local Characters = GetCharactersInRange(PrimaryPos, MaxRange)
	local CharactersInAngle = GetInAngle(PrimaryPos, Characters)
	
	for i, char in CharactersInAngle do
		local CharPos = GetPosition(char)
		local RayResult = workspace:Raycast(PrimaryPos, CFrame.lookAt(PrimaryPos, CharPos).LookVector * MaxRange, RayParams)
		
		--Remove the character if it's invalid (Not visible)
		if RayResult.Instance.Parent ~= char then
			table.remove(CharactersInAngle, i)
		end
	end
	
	print(CharactersInAngle)
end

You can customize the max values and params freely.
Just don’t set the angle above or below 0 - 360 degrees.

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