Unusually high rate on a simple module



So a while back i had my friend make a module that is made for raycasting and whose purpose is to serve as a raycaster for my gun system and i noticed that when i used this module in an actual game
it’s rate over a period of time would climb up to a rate that is unusual and too high, i don’t know why this happens because all that is going on is the module adding objects into a blacklist as long as they were objects that should be in a blacklist, such as accessories, tools, folders, and objects with certain names such as handle and effect, i’ll send code here

i tried changing the way the module adds stuff into the blacklist and nothing happens, that’s mostly it

--usage !!
-- rayHit, rayPosition, rayNormal = raycazt:Raycast(origin, direction, filterDescendantsTable, filterNamesTable, filterClassNamesTable, filterType, ignoreWater)
local playersService = game:GetService("Players")

local module = {}

-- ["Instance name"] = {"Class name 1", "Class name 2"}
local RayIgnoreNames = {
	["Bullet"] = {"Part", "MeshPart", "UnionOperation"},
	["Handle"] = {"Part", "MeshPart", "UnionOperation"},
	["Effect"] = {"Part", "MeshPart", "UnionOperation"},
	["HumanoidRootPart"] = {"Part", "MeshPart", "UnionOperation"},
	["Caches"] = {"Folder"},
	["DebrisFolder"] = {"Folder"},
	["Bullets"] = {"Folder"}
}

local RayIgnoreClasses = {"Accessory", "Hat", "Tool"}

local RayIgnoreWithChildNames = {
	["Humanoid"] = {"Humanoid"},
	["Health"] = {"NumberValue"}
}

local RayIgnoreWithChildClasses = {
	"Humanoid",
	"Accessory"
}

local RayWhitelist = {
	["Weakpoint"] = {"Part", "MeshPart", "UnionOperation"},
}

local RayBlacklist = {
	["HumanoidRootPart"] = {"Part", "MeshPart", "UnionOperation"},
	["Caches"] = {"Folder"},
	["DebrisFolder"] = {"Folder"},
	["Bullets"] = {"Folder"}
}

local blacklistedInstances = {}

local prin = function() end

local function raycast(ray:Ray, filterDescendantsTable:{Instance}, filterType:Enum.RaycastFilterType, ignoreWater:boolean, ShapeSize)
	local raycastParams = RaycastParams.new()

	raycastParams.FilterDescendantsInstances = filterDescendantsTable

	raycastParams.FilterType = filterType

	raycastParams.IgnoreWater = ignoreWater

	local raycastResult
	if not ShapeSize then
		raycastResult = workspace:Raycast(ray.Origin, ray.Direction, raycastParams)
	else
		raycastResult = workspace:Blockcast(CFrame.new(ray.Origin), Vector3.new(ShapeSize,ShapeSize,ShapeSize), ray.Direction, raycastParams)
	end
	local theRay = raycastResult
	local rayHit = raycastResult and raycastResult.Instance or nil
	local rayPosition = raycastResult and raycastResult.Position or ray.Origin + ray.Direction
	local rayNormal = raycastResult and raycastResult.Normal or nil
	return rayHit, rayPosition, rayNormal, theRay
end

local function checkInstance(filterDescendantsTable:{Instance}, filterDescendant:Instance)
	for index, descendant in pairs(filterDescendantsTable) do
		if filterDescendant == descendant or filterDescendant:IsDescendantOf(descendant) then
			return true
		end
	end
end

local function checkName(filterNamesTable:{[string]:{string}}, filterName:string, filterClassName:string)
	for name, className in pairs(filterNamesTable) do
		if name == filterName and table.find(className, filterClassName) then
			return true
		end
	end
end

local function checkClassName(filterClassNamesTable:{string}, filterClassName:string)
	for index, name in pairs(filterClassNamesTable) do
		if filterClassName == name then
			return true
		end
	end
end

local function checkChildrenName(instance:Instance, filterNamesTable:{[string]:{string}})
	for index, child in pairs(instance:GetChildren()) do
		local instanceNameIsListed = checkName(filterNamesTable, child.Name, child.ClassName)

		if instanceNameIsListed then
			return true
		end
	end
end

local function checkChildrenClassName(instance:Instance, filterClassNamesTable:{string})
	for index, child in pairs(instance:GetChildren()) do
		local instanceClassNameIsListed = checkClassName(filterClassNamesTable, child.ClassName)

		if instanceClassNameIsListed then
			return true
		end
	end
end

local function checkSiblingName(instance:Instance, filterNamesTable:{[string]:{string}})
	local instanceParent = instance.Parent

	if instanceParent ~= nil then
		local instanceParentsChildNameIsListed = checkChildrenName(instanceParent, filterNamesTable)

		if instanceParentsChildNameIsListed then
			return true
		end
	end
end

local function checkSiblingClassName(instance:Instance, filterClassNamesTable:{string})
	local instanceParent = instance.Parent

	if instanceParent ~= nil then
		local instanceParentsChildClassNameIsListed = checkChildrenClassName(instanceParent, filterClassNamesTable)

		if instanceParentsChildClassNameIsListed then
			return true
		end
	end
end

local function CheckRequirements(Child)
	-- return false if the child's name is assigned on the whitelist
	if RayWhitelist[Child.Name] and RayWhitelist[Child.Name][Child.ClassName] then
		return false
		-- otherwise we browse through the blacklist for the child's name
	elseif RayBlacklist[Child.Name] and RayBlacklist[Child.Name][Child.ClassName] then
		return true
	end
end

local function checkRayIgnore(instance:Instance, filterDescendantsTable:{Instance}, filterNamesTable:{[string]:{string}}, filterClassNamesTable:{string}, filterChildNamesTable:{[string]:{string}}, filterChildClassNamesTable:{string}, whitelist:{[string]:{string}}, filterType:Enum.RaycastFilterType, ignorePlayers, respectCanCollide)
	local willIgnorePlayers = ignorePlayers or false
	local isBlacklist = filterType == Enum.RaycastFilterType.Exclude

	local instanceIsListed = checkInstance(filterDescendantsTable, instance)
	local instanceNameIsListed = checkName(filterNamesTable, instance.Name, instance.ClassName)
	local instanceClassNameIsListed = checkClassName(filterClassNamesTable, instance.ClassName)
	local instancesChildNameIsListed = checkChildrenName(instance, filterChildNamesTable)
	local instancesChildClassNameIsListed = checkChildrenClassName(instance, filterChildClassNamesTable)
	local instancesSiblingNameIsListed = checkSiblingName(instance, filterChildNamesTable)
	local instancesSiblingClassNameIsListed = checkSiblingClassName(instance, filterChildClassNamesTable)
	local instanceNameIsWhitelisted = checkName(whitelist, instance.Name, instance.ClassName)

	local canCollide = true

	--if instance:IsA("BasePart") and respectCanCollide then
	--	canCollide = instance.CanCollide
	--end

	local listed = ((instanceClassNameIsListed or not canCollide) -- All this and still can't detect an accessory
		and not (instancesChildNameIsListed or instancesChildClassNameIsListed)
		and not (instancesSiblingNameIsListed or instancesSiblingClassNameIsListed)
		or instanceNameIsListed -- top proirity to inform <- false information
		or instanceIsListed) 
		and not instanceNameIsWhitelisted

	local isAPlayerCharacter = willIgnorePlayers == true and playersService:GetPlayerFromCharacter(instance.Parent) ~= nil
	local doIgnore = (isBlacklist and listed) or (not isBlacklist and not listed) or isAPlayerCharacter

	return doIgnore
end


function module:IsObjectInTheBlacklist(Object) -- Thing is weird
	local Find = table.find(blacklistedInstances, Object)
	for i, v in blacklistedInstances do
		if Object:IsDescendantOf(v)  then
			Find = table.find(blacklistedInstances, v)
			for _, o in v:GetDescendants() do
				local TempFind = table.find(blacklistedInstances, o)
				if TempFind then -- thinking?
					table.remove(blacklistedInstances, TempFind)
				end
			end
		end
	end
	for s, ex in Object:GetDescendants() do
		local ExFind = table.find(blacklistedInstances, ex)
		if ExFind then
			table.remove(blacklistedInstances, ExFind)
		end
	end
	return Find and true or false
end

local function addDescendant(descendant:Instance)
	if not module:IsObjectInTheBlacklist(descendant) then
		if descendant and checkRayIgnore(descendant, {}, RayIgnoreNames, RayIgnoreClasses, RayIgnoreWithChildNames, RayIgnoreWithChildClasses, RayWhitelist, Enum.RaycastFilterType.Exclude, false, false) or descendant:IsA("Tool") or descendant:IsA("Hat") or descendant:IsA("Accessory") then
			table.insert(blacklistedInstances, descendant)
		end
	end
end

local function ListAll() 
	local LastTick = tick()
	for index, Child in pairs(workspace:GetDescendants()) do
		--if Child:IsA("Tool") or Child:IsA("Hat") or Child:IsA("Accessory") then
		addDescendant(Child) -- This is only once so it should be fine
		--table.insert(blacklistedInstances, Child)
		--end
	end
	local CurrentTick = tick()
	prin = print
	prin("Prelisting completed in "..tostring(CurrentTick-LastTick).." seconds with a total of "..tostring(#blacklistedInstances).." instances")
	prin(blacklistedInstances)
end


local function removeDescendant(descendant:Instance) 
	local index = table.find(blacklistedInstances, descendant)
	if index then
		table.remove(blacklistedInstances, index)
	end
end

function module:Raycast(origin:Vector3, direction:Vector3, filterDescendantsTable:{Instance}, filterNamesTable:{string}, filterClassNamesTable:{string}, filterType:Enum.RaycastFilterType, ignoreWater:boolean, ignoresPlayers)
	filterDescendantsTable = filterDescendantsTable or {}
	filterType = filterType or Enum.RaycastFilterType.Exclude

	local NEWfilterDescendantsTable = table.clone(filterDescendantsTable)

	for index, blacklistedInstance in pairs(blacklistedInstances) do
		table.insert(NEWfilterDescendantsTable, blacklistedInstance) 
	end

	local position = origin + direction
	local unit = direction.Unit
	local length = direction.Magnitude


	local rayHit, rayPosition, rayNormal, cast  = raycast(Ray.new(origin + (unit * 0.01), direction), NEWfilterDescendantsTable, Enum.RaycastFilterType.Exclude, ignoreWater)

	if rayHit then
		local newLength = (position - rayPosition).Magnitude

		--if checkRayIgnore(rayHit, filterDescendantsTable, filterNamesTable, filterClassNamesTable, filterType) and newLength > 0 then
		--return module:Raycast(rayPosition, unit * newLength, filterDescendantsTable, filterNamesTable, filterClassNamesTable, filterType, ignoreWater)
		--end
	end

	return rayHit, rayPosition, rayNormal, cast
end

function module:Shapecast(Origin:Vector3, Size:Number, Direction:Vector3, IgnoreList, IgnoreNames)
	IgnoreList = IgnoreList or {}

	local NEWfilterDescendantsTable = table.clone(IgnoreList)

	for index, blacklistedInstance in pairs(blacklistedInstances) do
		table.insert(NEWfilterDescendantsTable, blacklistedInstance)
	end

	local NewDirection = Direction.Unit * 1000
	local rayHit, rayPosition, rayNormal, cast = raycast(Ray.new(Origin + (Direction.Unit * 0.01), NewDirection), IgnoreList, Enum.RaycastFilterType.Exclude, true, Size)

	return rayHit, rayPosition, rayNormal, cast
end

local started = false

function module:PowerOn() -- Turn the module on and get it working
	if not started then
		debug.setmemorycategory("Raycazting")
		started = true

		--task.spawn(ListAll)
		ListAll()

		--workspace.DescendantAdded:Connect(addDescendant)
		workspace.DescendantRemoving:Connect(removeDescendant)

		workspace.DescendantAdded:Connect(function(Child)
			if checkRayIgnore(Child, {},
				RayIgnoreNames, RayIgnoreClasses, RayIgnoreWithChildNames, RayIgnoreWithChildClasses, RayWhitelist,
				Enum.RaycastFilterType.Exclude, false, false) or
					Child:IsA("Tool") or Child:IsA("Hat") or Child:IsA("Accessory") then -- Forced to do this because this module is too sped to use the actual checkrayignore to add these objects to the list
				--addDescendant(Child) 
				table.insert(blacklistedInstances, Child)
			end
		end)
	end 
end

function module:GetBlacklist()
	return blacklistedInstances
end

return module
1 Like

Why not just ask your friend that ma\de the module?

i have multiple times and he couldn’t figure it out
We’ve tried to fix it together and we just couldn’t get it to be normal

Well it sounds like you may have some memory leaks. Nothing I can really do here and I’m not particularly qualified on scripts this complex. Debugging is about the only thing I can suggest. Try turning off all the guns and start one at a time. Check any threads executed are being handled correctly. Programming can be fickle sometimes.

This is precisely how the rate goes up and yes the game does have a memory leak.