How do I fix this sorting for my RTS attack detection

I have an issue, my RTS game’s attack detection seems to be biased off the order which my RTS units are alphabetically sorted.
This is a question I’ve asked before, but I’m not really happy with my answer (it lags to high degrees even past 100 units).
My previous answer did essentially work but I think there’s a better way to do it, I just can’t figure it out. Previously, I was sorting a table with every unit I added and doing a magnitude check. However I was advised that magnitude checks for very high number of units is not too optimized (I would have to nest my loop, making it search through units^2).
So I’ve resorted to doing GetPartsInRadius with some overlap params. I also wanted to remove my previous table sort algorithm because it would severely lag my game on the server past 256 units. I’ve seen Roblox games such as Normal RTS and Medieval RTS be able to handle a lot more units and work a-okay (for the most part).

Is there really a way to optimize this further, without my detection being biased?
(For the code sample, I’m sending the entire thing but you only need to look at TargetLogic for attack and the while true do loop.)
https://gyazo.com/90b113be310f61c76d36657290fb89e4
https://gyazo.com/5d1084d7b242c87db9b5a0cb0e0e7c88

local target = nil
local teams = workspace.InitializedUnits:GetDescendants()
local function TargetLogic(Unit, TargetType)
	if TargetType == "Attack" then
		local ovParams = OverlapParams.new()
		ovParams.MaxParts = 10 -- fidelity
		ovParams.CollisionGroup = "Units"
		ovParams.FilterType = Enum.RaycastFilterType.Exclude
		ovParams.FilterDescendantsInstances = Unit.Parent.Parent:GetChildren()
		local thing = workspace:GetPartBoundsInRadius(Unit.Position, 10, ovParams)
		for i, Target in thing do
			local EnemyMovementType = Target.Parent.Detection.Movement.Value -- The type of plane the target is travelling on (i.e, air, ground)
			local TargetDetection = Unit.Parent.Detection.TargetDetection.Value -- What the unit can detect (i.e, it detects air, ground, or both)
			if TargetDetection == EnemyMovementType or TargetDetection == "AttackAll" then  -- If it just has the thing "AttackAll", there's no need to check the other variables, this is bruteforce
				Target = thing[1]
				return Target
			end
		end
	end
	if TargetType == "Heal" then
		local ovParams = OverlapParams.new()
		ovParams.MaxParts = 1 -- fidelity
		ovParams.CollisionGroup = "Units"
		ovParams.FilterType = Enum.RaycastFilterType.Include
		ovParams.FilterDescendantsInstances = Unit.Parent.Parent:GetChildren()
		local thing = workspace:GetPartBoundsInRadius(Unit.Position, 10, ovParams)
		for _, Target in thing do 
			local EnemyMovementType = Target.Parent.Detection.Movement.Value -- The type of plane the target is travelling on (i.e, air, ground)
			local TargetDetection = Unit.Parent.Detection.TargetDetection.Value -- What the unit can detect (i.e, it detects air, ground, or both)
			if TargetDetection == EnemyMovementType or TargetDetection == "AttackAll" then -- If it just has the thing "AttackAll", there's no need to check the other variables, this is bruteforce
			end
		end
	end
	if TargetType == "Build" then
		local ovParams = OverlapParams.new()
		ovParams.MaxParts = 1 -- fidelity
		ovParams.CollisionGroup = "Units"
		ovParams.FilterType = Enum.RaycastFilterType.Include
		ovParams.FilterDescendantsInstances = Unit.Parent.Parent:GetChildren()
		local thing = workspace:GetPartBoundsInRadius(Unit.Position, 10, ovParams)
		for _, Target in thing do local EnemyMovementType = Target.Parent.Detection.Movement.Value -- The type of plane the target is travelling on (i.e, air, ground)
			local TargetDetection = Unit.Parent.Detection.TargetDetection.Value -- What the unit can detect (i.e, it detects air, ground, or both)
			if Target.Parent:GetAttribute("Status") == "Building" and Target.Parent:GetAttribute("BuilderCount") < Target.Parent:GetAttribute("buildMax") then
			end
		end
	end
end

local function Attack(Unit)
	local Target = TargetLogic(Unit, "Attack")
	if Target and Target.Parent and Unit and Unit.Parent and
		Unit.Parent:GetAttribute("VfxFired") == false then
		Unit.Parent:SetAttribute("VfxFired", true)
		Target.Parent:Destroy()
		task.wait(Unit.Parent:GetAttribute("FireDelay"))
		if Unit and Unit.Parent then
			Unit.Parent:SetAttribute("VfxFired", false)
		end
	end
end

local function Heal(Unit)
	local Target = TargetLogic(Unit,"Heal")
	if Target and Target.Parent and Unit and Unit.Parent then
		print("Healing sucessful")
	end
end

local function Build(Unit)
	local Target = TargetLogic(Unit,"Build")
	if Target and Target.Parent and Unit and Unit.Parent then
		if Unit.Parent:GetAttribute("VfxFired") == false then
			Unit.Parent:SetAttribute("VfxFired", true)
			if Target.Parent:GetAttribute("BuilderCount") < Target.Parent:GetAttribute("buildMax") then
				Target.Parent:SetAttribute("BuilderCount", Target.Parent:GetAttribute("BuilderCount") + 1)
				print(Unit.Parent)
				task.wait(Unit.Parent:GetAttribute("fireDelay"))
				Unit.Parent:SetAttribute("VfxFired", false)
			end
		end
	end
end
while task.wait(0.35) do
	for _, SelectUnit in teams do
		if SelectUnit:IsA("Model") then
			local Unit = SelectUnit.PrimaryPart
			if Unit and Unit.Parent then
				if Unit.Parent:GetAttribute("Status") == "Attacker" then
					task.spawn(function()
						Attack(Unit)
					end)
				end
				if Unit.Parent:GetAttribute("Status") == "Healer" then
					task.spawn(function()
						Heal(Unit)
					end)
				end
				if Unit.Parent:GetAttribute("Status") == "Builder" then
					task.spawn(function()
						Build(Unit)
					end)
				end
			end
		end
	end
end

Bump


you can use the octree module for efficiently getting the closest enemy
you can also use table.sort() for fast sorting of tables

i dont know what you mean by biased but if you mean the enemy targets then you can put all of the valid targets in a table and then choose from them randomly