A simple raycast module

I made a module that can perform raycasts pretty easily, its simple and lightweight.
But it doesn’t just do that, it also has getpartsinbox and getpartsinradius functions.

local raycastingModule = {};

raycastingModule.OverlapParamsNew = OverlapParams.new;
raycastingModule.RaycastParamsNew = RaycastParams.new;

type typechecking = {
	OverlapParamsNew  : () -> OverlapParams,
	RaycastParamsNew  : () -> RaycastParams,

	performRaycast : (self : typechecking, partOrOrigin : BasePart | Vector3, directionOrLength : number? | Vector3, RaycastParams : RaycastParams?) -> RaycastResult?,
	GetPartsInBox : (self : typechecking, boxCFrame : CFrame | Vector3, boxSize : Vector3, OverlapParams : OverlapParams?) -> {Instance}?,
	GetPartsInRadius : (self : typechecking, boxPosition : Vector3, boxRadius : number, OverlapParams : OverlapParams?) -> {Instance}?,
	GetTouchingParts : (self : typechecking, part : BasePart) -> {Instance}?,
}

if script and script:GetActor() then
	task.desynchronize();
end

--Raycasting--
--------------
function raycastingModule:performRaycastFromDirection(origin : Vector3, direction : Vector3, ... : RaycastParams)
	assert(origin and direction, "Arguments missing or nil")

	local success, raycastResult = pcall(workspace.Raycast, workspace, origin, direction, ...);
	return (success and raycastResult) or nil :: RaycastResult?
end

function raycastingModule:performRaycastFromPart(part : BasePart, lengthOfRay : number?,... : RaycastParams)
	assert(part, "Argument 1 missing or nil")

	local params = ...;
	if params == nil then
		params = RaycastParams.new();

		params.FilterType = Enum.RaycastFilterType.Exclude
		table.insert(params.FilterDescendantsInstances, part);
	end

	local success, raycastResult = pcall(workspace.Raycast, workspace, part.Position, part.CFrame.LookVector * (lengthOfRay or 9e9) , ...);
	return (success and raycastResult) or nil :: RaycastResult?
end

-- Boxes and radiuses --
------------------------

function raycastingModule:GetPartsInBox(boxCFrame : Vector3 | CFrame, boxSize : Vector3, ... : OverlapParams)
	assert(boxCFrame, "Arguments missing or nil");
	
	if typeof(boxCFrame) == "Vector3" then
		boxCFrame = CFrame.new(boxCFrame);
	end

	local success, boundingParts = pcall(workspace.GetPartBoundsInBox, workspace, boxCFrame, boxSize, ...)
	local parts = (success and boundingParts) or nil;

	return parts :: {Instance}?
end

function raycastingModule:GetPartsInRadius(boxPosition : Vector3, boxRadius : number, ... : OverlapParams)
	assert(boxPosition, "Arguments missing or nil");

	local success, boundingParts = pcall(workspace.GetPartBoundsInRadius, workspace, boxPosition, boxRadius, ...)
	local parts = (success and boundingParts) or nil;

	return parts :: {Instance}?
end

function raycastingModule:performRaycast(partOrOrigin : BasePart | Vector3, directionOrLength : number? | Vector3, ... : RaycastParams)
	if typeof(partOrOrigin) == "Vector3" then
		return raycastingModule:performRaycastFromDirection(partOrOrigin, directionOrLength, ...);
	elseif typeof(partOrOrigin) == "Instance" and partOrOrigin:IsA("BasePart") then
		return raycastingModule:performRaycastFromPart(partOrOrigin, directionOrLength, ...);
	end
	return error();
end

function raycastingModule:GetTouchingParts(part : BasePart)
	assert(typeof(part) == "Instance" and part:IsA("BasePart"), "Argument 1 missing or nil");
	local params = raycastingModule.OverlapParamsNew();
	
	params.FilterType = Enum.RaycastFilterType.Exclude;
	params.FilterDescendantsInstances = {part};
	params.RespectCanCollide = true;
	
	local instances = raycastingModule:GetPartsInBox(part.CFrame, part.Size, params);
	return instances
end


return raycastingModule :: typechecking;

use it in your games if you want to.

1 Like