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.