How can I increase this script's performance?

So, I have this script which runs every time a round starts (Every few minutes). It basically checks for all proximity prompts using :GetDescendants and decreases how much time it takes to use them. This works, but I’m wondering, since the game has thousands of instances, won’t it take alot of power to do it? Is there a way to increase this script’s performance; example: something like :GetDescendantsOfClass()

(The script is a local script)
Script:

game.ReplicatedStorage.FixingSpeedUpgrade.OnClientEvent:Connect(function()
	task.wait(5)	-- Letting some time pass so the map is already loaded (For StreamingEnabled)
	local plr = game.Players.LocalPlayer
	local Map = game.Workspace.Map:GetChildren()[1]	-- The map where the proximity prompts shold be
	if Map then	-- If the map exists, do :GetDescendants on it to increase performance
		for i,v in pairs(Map:GetDescendants()) do
			if v:IsA("ProximityPrompt") then
				if v:GetAttribute("Type") and v:GetAttribute("Type") == "Fixable" then
					v.HoldDuration = v.HoldDuration - (plr.Upgrades.FixingSpeed.Value * 0.5)
				end
			end
		end
	else	-- If the map doesn't exist for some reason, use :GetDescendants on the whole workspace (There is only the map and the lobby, but combined they have thousands of Instances.)
		task.wait(1)	-- Maybe now the map has loaded
		for i,v in pairs(game.Workspace:GetDescendants()) do
			if v:IsA("ProximityPrompt") then
				if v:GetAttribute("Type") and v:GetAttribute("Type") == "Fixable" then
					v.HoldDuration = v.HoldDuration - (plr.Upgrades.FixingSpeed.Value * 0.5)
				end
			end
		end
	end
end)

Also, is this easily exploitable?

-- If the map doesn't exist for some reason, use :GetDescendants on the whole workspace 
task.wait(1)	-- Maybe now the map has loaded
		for i,v in pairs(game.Workspace:GetDescendants()) do
			if v:IsA("ProximityPrompt") then
				if v:GetAttribute("Type") and v:GetAttribute("Type") == "Fixable" then
					v.HoldDuration = v.HoldDuration - (plr.Upgrades.FixingSpeed.Value * 0.5)
				end
			end
		end

You can make a Descendants variable which goes through this without introducing more code.

local Map = game.Workspace:FindFirstChild("Map")
local MapDescendants = if Map then Map:GetChildren()[1] else workspace:GetDescendants() -- Use workspace descendants if the Map doesn't exist
for i,v in pairs(MapDescdentants) do
	if v:IsA("ProximityPrompt") then
		if v:GetAttribute("Type") and v:GetAttribute("Type") == "Fixable" then
			v.HoldDuration = v.HoldDuration - (plr.Upgrades.FixingSpeed.Value * 0.5)
		end
	end
end

Also you could put all proximity prompts in one CollectionService Tag and then just increase the HoldDuration for them.

1 Like

Thanks, this can help. I’m not sure if I’ll use collection service though as the proximity prompts aren’t made from before but created every map.

For now, I won’t mark you as a solution just in case anyone else has a better one.

A much more flexible solution would be to listen to use CollectionService and listen to its events for when a tagged instance gets added/removed.

local Player: Player = game:GetService("Players").LocalPlayer
local CollectionService: CollectionService = game:GetService("CollectionService")

local Remote: RemoteEvent = game:GetService("ReplicatedStorage").Remote

local ProximityPrompts: {ProximityPrompt} = {}


local function OnClientEvent()
	for _, ProximityPrompt: ProximityPrompt in ProximityPrompts do
		...
	end
end

local function HandleTaggedPrompts()
	local TaggedPrompts: {any} = CollectionService:GetTagged("ProximityPrompt")
	table.move(TaggedPrompts, 1, #TaggedPrompts, 1, ProximityPrompts)

	CollectionService:GetInstanceAddedSignal("ProximityPrompt"):Connect(function(ProximityPrompt: ProximityPrompt)
		table.insert(ProximityPrompts, ProximityPrompt)
	end)

	CollectionService:GetInstanceRemovedSignal("ProximityPrompt"):Connect(function(ProximityPrompt: ProximityPrompt)
		local Index: number? = table.find(ProximityPrompts, ProximityPrompt)
		if Index then
			table.remove(ProximityPrompts, Index)
		end
	end)
end


HandleTaggedPrompts()
Remote.OnClientEvent:Connect(OnClientEvent)

Mind the Type-Checking, I may be a little overzealous with it :upside_down_face:

2 Likes