Cylinder-Based Raycast Hitbox

Hello!

This is a simple module I made for my own purposes. I thought I would open-source it so that others may use it as well.

What it does

This generates a cylinder from raycasts to detect if anything is colliding.
If something is colliding, you will be given a RaycastResult.

Source code

This is a module script.

local RadialRaycastCheck = {}

type array<t> = {[number]:t} -- Array variable type
type dictionary<t> = {[string]:t} -- Dictionary variable type

local RaycastPar = RaycastParams.new()
RaycastPar.FilterType = Enum.RaycastFilterType.Blacklist

local PropertyChecks = { -- If any of these are true during the property check, it is ignored in collision
	CanCollide = false,
	Transparency = 1,
}

local function CreateCylinderArray(Position: CFrame, Height: number) -- math :c
	local PositionsArray: array<CFrame> = {}
	
	local BasePosition = CFrame.new(Position.X, 0, Position.Z)
	
	for PosY = Position.Y-Height/2, Position.Y+Height/2, Height/2 do
		for Rotation = 0, math.pi*2, math.pi/30 do
			local NewCFrame = BasePosition * CFrame.new(0, PosY, 0) * CFrame.fromEulerAnglesXYZ(0, Rotation, 0)
			table.insert(PositionsArray, NewCFrame)
		end
	end
	
	return PositionsArray
end

function RadialRaycastCheck:Check(Position: CFrame, Radius: number, Height: number, Ignore: array<any>)
	local NewCylinder = CreateCylinderArray(Position, Height)
	RaycastPar.FilterDescendantsInstances = Ignore
	
	local CollisionResult = nil -- Will be a RaycastResult 
	
	for _, CheckCFrame: CFrame in pairs(NewCylinder) do
		local RaycastResult = workspace:Raycast(CheckCFrame.Position, CheckCFrame.LookVector * Radius, RaycastPar)
		local RaycastInstance = RaycastResult and RaycastResult.Instance
		
		if RaycastInstance then
			local DidCollide = true
			
			for Property, Value in pairs(PropertyChecks) do
				if RaycastInstance[Property] == Value then
					DidCollide = false
					break
				end
			end
			
			if DidCollide then
				CollisionResult = RaycastResult
				break
			end
		end
	end
	
	return CollisionResult
end

return RadialRaycastCheck

How to use it

It’s simple to use!

  • Get the module via require
  • To raycast radially, do module:Check(Position, Radius, Height, IgnoreList)

And that’s it! It will return either a RaycastResult or nil.

10 Likes

This looks awesome! I was planning on doing something like this, but now I don’t have to. :grinning_face_with_smiling_eyes:

I was planning on using a different formula, however.

2 Likes

this is somewhat i need for projectile-based gun system. so thank you.!
by the way, will you add more hitbox classes such as boxcast, spherecast? and vector direction feature for it?

im sorry if i ask you too many questions

1 Like

Have you done any benchmarks to see how fast this runs?

1 Like

I don’t know if I will, I only made this since I needed it.

1 Like

The following benchmark is completed with boatbomber’s benchmarking plugin:

About 626 ms frame time. Definitely not too expensive, but don’t use it every frame just in case.

Hey! :wave:

Nice job!

I thought I’d mention that I think this script could be improved by specifying how exactly it works.

What I mean is, at first I had a hard time understanding whether this script would shoot a ray out from the CFrame parameter ‘Position’ and use the CFrames Orientation to know in which direction to shoot, or if it would spawn a ‘cylinder’ of rays at the Position parameter, and have every ray point downward/upward to a certain extent. :thinking:

After inspecting your script I now understand that the best way to illustrate your script is like this:

Does this illustration accurately describe what your Cylinder of Rays might look like? :smile:

Point is it would help clarify how the ‘Cylinder Based Raycast Hitbox’ works.
Nonetheless its a good script :+1:

1 Like

Yes, that is a good demonstration for the raycasting!

2 Likes