GetPartsInPart() being slow

I’m just trying to make an area invisibility move. I use a sphere hitbox and it’s supposed to add objectvalues of the characters that are inside the sphere but instead it does it for players first then wait a few seconds until finally making the player invisible. Then a few more seconds so it can detect NPCs…

local functions = {}
local targets = {}
local remote = game.ReplicatedStorage.RemoteEvents.Suke.Invisible

function functions.Start(plr)
	local tweeninfo = TweenInfo.new(0.5, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut)
	local tweenservice = game:GetService("TweenService")
	local chr = plr.Character
	local hum = chr:FindFirstChildOfClass("Humanoid")
	local health = hum.Health
	sphere = script.Sphere:Clone()
	sphere.Parent = workspace.Effects
	sphere.Position = chr.HumanoidRootPart.Position
	local tween = tweenservice:Create(sphere, tweeninfo, {Size = Vector3.new(50.75, 50.75, 50.75)})
	
	tween:Play()
	
	local aoe = workspace:GetPartsInPart(sphere)
	
	for i, a in pairs(aoe) do
		if a:IsDescendantOf(workspace.NPCs) then
			for i, v in pairs(a.Parent:GetDescendants()) do
				if (v:IsA("BasePart") or v:IsA("Decal") and v.Name ~= "HumanoidRootPart") then
					v.Transparency = 1
					local new = Instance.new("ObjectValue")
					new.Parent = sphere
					new.Name = a.Parent.Name
					new.Value = a.Parent
				elseif v:IsA("BillboardGui") then
					v.Enabled = false
				end
			end
		elseif a:IsDescendantOf(workspace.Players) then
			for i, v in pairs(a.Parent:GetDescendants()) do
				if (v:IsA("BasePart") or v:IsA("Decal") and v.Name ~= "HumanoidRootPart") then
					v.Transparency = 1
					remote:InvokeClient(game.Players:GetPlayerFromCharacter(a.Parent), 0.7)
					local new = Instance.new("ObjectValue")
					new.Parent = sphere
					new.Name = a.Parent.Name
					new.Value = a.Parent
				elseif v:IsA("BillboardGui") then
					v.Enabled = false
				end
			end
		end
	end
	
	for i, part in pairs(chr:GetDescendants()) do
		if (part.Name ~= "HumanoidRootPart" and part:IsA("MeshPart") or part:IsA("Part")  and  part.Name ~= "HumanoidRootPart") then
			local tween2 = tweenservice:Create(part, tweeninfo, {Transparency = 1})
			tween2:Play()
			part.Material = Enum.Material.Glass
		elseif part:IsA("BillboardGui") then
			part.Enabled = false
		elseif part:IsA("Decal") then
			local tween3 = tweenservice:Create(part, tweeninfo, {Transparency = 1})
			tween3:Play()
		end
	end
	
	print("STARTED")

end

function functions.End(plr)
	local tweeninfo = TweenInfo.new(0.5, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut)
	local tweenservice = game:GetService("TweenService")
	local chr = plr.Character
	local hum = chr:FindFirstChildOfClass("Humanoid")
	local health = hum.Health

	for i, part in pairs(chr:GetDescendants()) do
		if part:IsA("BasePart") or part:IsA("Decal") and part.Name ~= "HumanoidRootPart" then
			local tween2 = tweenservice:Create(part, tweeninfo, {Transparency = 0})
			tween2:Play()
			part.Material = Enum.Material.SmoothPlastic
		elseif part:IsA("BillboardGui") then
			part.Enabled = true
		end
	end
	
	for i, tab in pairs(sphere:GetChildren()) do
		if tab:IsA("ObjectValue") then
			if tab.Value:IsA("Model") then
				if tab.Value:IsDescendantOf(workspace.NPCs) then
					for i, v in pairs(tab.Value:GetDescendants()) do
						if (v:IsA("BasePart") or v:IsA("Decal") and v.Name ~= "HumanoidRootPart") then
							local tween2 = tweenservice:Create(v, tweeninfo, {Transparency = 1})
							tween2:Play()
						elseif v:IsA("BillboardGui") then
							v.Enabled = false
						end
						print("NPC 2")
						tab:Destroy()
					end
				elseif tab.Value:IsDescendantOf(workspace.Players) then
					for i, v in pairs(tab.Value:GetDescendants()) do
						local playar = game.Players:GetPlayerFromCharacter(tab.Value)
						if (v:IsA("BasePart") or v:IsA("Decal") and v.Name ~= "HumanoidRootPart") then
							local tween2 = tweenservice:Create(v, tweeninfo, {Transparency = 1})
							tween2:Play()
						elseif v:IsA("BillboardGui") then
							v.Enabled = false
						end
						print("Player 2")
						tab:Destroy()
					end
				end
			end
		end
	end
	
	print("ENDED")
	
end

return functions

The problem is at the start one.

As stated in Introducing OverlapParams - New Spatial Query API, :GetPartsInPart() checks the actual geometry of the part as opposed to its bounding box. Hence, it will not be as performant as other options. (Assuming this is not an issue with the code below it or your serverside code)

Consider using :GetPartBoundsInBox().

I see, would you mind giving me an example code for GetPartBoundsInBox()? I’m not that fast at learning stuff and I’m not smart for these kind of things xD.

Given Part is an anchored part in workspace with CanCollide disabled:

local Part = workspace:WaitForChild("Part")

local partsInBoundingBox = workspace:GetPartBoundsInBox(Part.CFrame, Part.Size, nil) -- Replace nil with OverlapParams if you are using them

So how would I loop through it and detect if the parts are of a character’s?

Just replace:

local aoe = workspace:GetPartsInPart(sphere)

With:

local aoe = workspace:GetPartBoundsInBox(sphere.CFrame, sphere.Size, nil)

I will try this and let you know how it goes, thanks.

It still does the same thing, except it doesn’t set the transparency of the NPCs at all.
Also it spams the instance.new
https://gyazo.com/a28e8e8e962df4450595d6723f3b6065

Where are you calling functions.Start()?

I have a remote event that searches for the move’s modulescripts and the remote event is being fired from a localscript that I have as the “Suke Combat” tool script
I can show u the localscript and remote script if u want

Moves Localscript in tool
local UIS = game:GetService("UserInputService")
local RS = game:GetService("ReplicatedStorage")
local Modules = RS:WaitForChild("Modules")
local Fruit = Modules:WaitForChild("Fruit")
local HM = Modules:WaitForChild("Handlers")
local Tool = script.Parent
local Player = game.Players.LocalPlayer
local remote = RS.RemoteEvents.Fruit
local PlayerGui = Player:WaitForChild("PlayerGui")
local Character = Player.Character or Player.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")
local Cooldown1 = false
local Holding1 = false
local Cooldown2 = false
local Holding2 = false
local Debounce = 1
local Mouse = Player:GetMouse()
local track1 = Humanoid:LoadAnimation(Tool.Animations.Spin)
local tweeninfo = TweenInfo.new(1.5, Enum.EasingStyle.Linear, Enum.EasingDirection.InOut)
local ts = game:GetService("TweenService")

local function zmove()
	Tool.Active.Value = "Z"
	remote:FireServer("Suke", "Self Invisibility", "Start")
	wait(2)
	for i, v in pairs(Character:GetDescendants()) do
		if (v.Name ~= "HumanoidRootPart" and v:IsA("MeshPart") or v:IsA("Part")  and  v.Name ~= "HumanoidRootPart") then
			v.Transparency = 0.7
		elseif v:IsA("Decal") then
			v.Transparency = 0.7
		end
	end
	wait(10)
	for i, v in pairs(Character:GetDescendants()) do
		if (v.Name ~= "HumanoidRootPart" and v:IsA("MeshPart") or v:IsA("Part")  and  v.Name ~= "HumanoidRootPart") then
			v.Transparency = 0
		elseif v:IsA("Decal") then
			v.Transparency = 0
		end
	end
	remote:FireServer("Suke", "Self Invisibility", "End")
	Tool.Active.Value = "None"
end

local function xmove()
	Tool.Active.Value = "X"
	remote:FireServer("Suke", "Area Invisibility", "Start")
	for i, v in pairs(Character:GetDescendants()) do
		if (v.Name ~= "HumanoidRootPart" and v:IsA("MeshPart") or v:IsA("Part")  and  v.Name ~= "HumanoidRootPart") then
			v.Transparency = 0.7
		elseif v:IsA("Decal") then
			v.Transparency = 0.7
		end
	end
	wait(10)
	remote:FireServer("Suke", "Self Invisibility", "End")
	Tool.Active.Value = "None"
end

UIS.InputBegan:Connect(function(Input)
	if Input.KeyCode == Enum.KeyCode.E and Debounce == 1 and Tool.Equip.Value == true and Tool.Active.Value == "None"  and Cooldown1 == false then
		Debounce = 2
		local HIS = Tool.Animations["Area Charge"]
		HoldTrack = Player.Character.Humanoid:LoadAnimation(HIS)
		HoldTrack:Play()
		for i = 1,math.huge do
			if Debounce == 2 then
				local RootPos, MousePos = Player.Character.HumanoidRootPart.Position, Mouse.Hit.Position
				Player.Character.HumanoidRootPart.CFrame = CFrame.new(RootPos, Vector3.new(MousePos.X, RootPos.Y, MousePos.Z))
				Player.Character.HumanoidRootPart.Anchored = true
			else
				break
			end
			wait()
		end
	elseif Input.KeyCode == Enum.KeyCode.Z and Tool.Equip.Value == true and Tool.Active.Value == "None"  and Cooldown1 == false then
		track1:Play()
		zmove()
		Cooldown1 = true
		wait(3)
		Cooldown1 = false
	end
end)

UIS.InputEnded:Connect(function(Input)
	if Input.KeyCode == Enum.KeyCode.E and Debounce == 2 and Tool.Equip.Value == true and Tool.Active.Value == "None" and Cooldown1 == false then
		Cooldown1 = true
		Debounce = 3
		local PIS = Tool.Animations["Area Release"]
		local PunchTrack = Player.Character.Humanoid:LoadAnimation(PIS)
		PunchTrack:Play()
		HoldTrack:Stop()
		PunchTrack:GetMarkerReachedSignal("Release"):Connect(function()
			xmove()
			task.wait(3)
			Cooldown1 = false
		end)
		wait(1)
		Player.Character.HumanoidRootPart.Anchored = false
		wait(2)
		Tool.Active.Value = "None"
		wait(0.1)
		Debounce = 1
	end
end)

The transparency part in the localscript makes it so the player can see himself after requiring the module.

Remote
local rs = game:GetService("ReplicatedStorage")
local remote = rs.RemoteEvents.Fruit
local modules = rs.Modules
local fruitmodules = modules.Fruit

remote.OnServerEvent:Connect(function(plr, ability, move, functions, option1, option2)
	if plr then
		for i, k in pairs(fruitmodules:GetChildren()) do
			if k.Name == tostring(ability) then
				local abilitymove = k[move]
				local required = require(abilitymove)
				required[functions](plr, option2)
			end
		end 
	end
end)