Enemy Spawn System Help

I am unsure on how to change these lines of codes to have an option of having a specific amount of “Enemies” spawned. Any help?

local function SpawnEnemy(Type)
local Enemy = game.ServerStorage.Enemies:FindFirstChild(Type):Clone()
local Alive = true
Enemy.Parent = workspace.Enemies

for i,Child in pairs(Enemy:GetChildren()) do
    if Child:IsA("BasePart") then
        Child.CanCollide = false
    end
end
1 Like

Like so:

local function SpawnEnemy(Count, Type)
    for i=1,Count do
        local Enemy = game:GetService("ServerStorage"):FindFirstChild("Enemies"):FindFirstChild(Type):Clone();
        local Alive = true;
        Enemy.Parent = workspace:FindFirstChild("Enemies");

        for i,Child in pairs(Enemy:GetChildren()) do
            if Child:IsA("BasePart") then
                Child.CanCollide = false;
            end
        end
    end
end

Basically what this does is it repeats the function for however many times you need the task completed.

1 Like

Thanks but this isn’t working alongside the other parts of the script.
Here is the full script

local Path = game:GetService(“PathfindingService”):ComputeSmoothPathAsync(workspace.Start.Position,workspace.Wall.Position + Vector3.new(3,0,0),500)
local Positions = Path:GetPointCoordinates()

math.randomseed(os.time())

local EnemyGroup = game:GetService(“PhysicsService”):CreateCollisionGroup(“Enemies”)
local PlayerGroup = game:GetService(“PhysicsService”):CreateCollisionGroup(“Players”)
game:GetService(“PhysicsService”):CollisionGroupSetCollidable(“Enemies”,“Players”,false)
–game:GetService(“PhysicsService”):CollisionGroupSetCollidable(“Enemies”,“Enemies”,false)
game:GetService(“PhysicsService”):CollisionGroupSetCollidable(“Players”,“Players”,false)

local function Bounty(Enemy)
local Total = Enemy.Bounty.Value

for i,Tag in pairs(Enemy.Credit:GetChildren()) do
	local Player = game.Players:FindFirstChild(Tag.Name)
	if Player then
		local Percent = Tag.Value / Enemy.MaxHealth.Value
		local Reward = math.ceil(Total * Percent)
		Player.leaderstats.Cash.Value = Player.leaderstats.Cash.Value + Reward
	end
end

end

local function SpawnEnemy(Type)
local Enemy = game.ServerStorage.Enemies:FindFirstChild(Type):Clone()
local Alive = true
Enemy.Parent = workspace.Enemies

for i,Child in pairs(Enemy:GetChildren()) do
	if Child:IsA("BasePart") then
		Child.CanCollide = false
	end
end	
local Objective 

Enemy.HumanoidRootPart.CFrame = workspace.Spawn.CFrame + Vector3.new(math.random(-4,4),0,math.random(-4,4))
local Index = 0

local function NextObjective(Success)
	if Success then
		Index = Index + 1
	end
	if Positions[Index] then
		Enemy.Humanoid:MoveTo(Positions[Index])
		Objective = Positions[Index]
	else
		local Explode = Instance.new("Explosion",workspace)
		Explode.Position = Enemy.HumanoidRootPart.Position
		Explode.BlastPressure = 0
		workspace.Wall.Health.Value = workspace.Wall.Health.Value - Enemy.Damage.Value
		Alive = false
		Enemy:Destroy()
	end
end

NextObjective(true)
Enemy.Humanoid.MoveToFinished:connect(function(Reached)
	-- if they are *close enough* consider it as good as the real deal?
	if not Reached then
		if (Enemy.HumanoidRootPart.Position - Objective).magnitude < 4 then
			print("Reached override")
			Reached = true
		end
	end
	NextObjective(Reached)
end)

Enemy.Health.Changed:connect(function()
	if Enemy.Health.Value < 0 then
		if Alive then
			Enemy:BreakJoints()
			Alive = false
			if Enemy.Head:FindFirstChild("Death") then
				Enemy.Head.Death:Play()
			end
			Bounty(Enemy)	
		end
		game.Debris:AddItem(Enemy,1)
	end
	Enemy.Humanoid.Health = (Enemy.Health.Value/Enemy.MaxHealth.Value) * 100
end)

for i,Part in pairs(Enemy:GetChildren()) do
	if Part:IsA("BasePart") then
		game:GetService("PhysicsService"):SetPartCollisionGroup(Part,"Enemies")
	end
end

if Enemy:FindFirstChild("WalkAnim") then
	local Track = Enemy.Humanoid:LoadAnimation(Enemy.WalkAnim)
	Track:Play()
--	Enemy.WalkAnim:Play()
end

end

wait(1)

for i,Wall in pairs(workspace.Path.Walls:GetChildren()) do
if Wall.Name == “Wall” and Wall:IsA(“BasePart”) then
Wall.Transparency = 1
Wall.CanCollide = false
end
end

while true do
wait(1)
local Chance = math.random(1,10)
if Chance == 7 then
SpawnEnemy(“Rich Dummy”)
else
SpawnEnemy(“Dummy”)
end

end

1 Like

At line 10 you have a syntax error:

–game:GetService(“PhysicsService”):CollisionGroupSetCollidable(“Enemies”,“Enemies”,false)

There’s just a single dash (-) at the beginning of the line, which doesn’t make sense in this context. You probably wanted to temporarily comment out the line with two dashes (--)?

Anyway, the SpawnEnemy function seems to be pretty self contained, and you’re calling it periodically in the while loop at the bottom of the script. If I understand correctly, you want to change it so that it keep spawning enemies until it reaches a certain limit, and then waits for enemies to die before spawning new ones?

In that case, you need some way of keeping track of how many enemies are currently alive. You could do that with a simple counter variable (e.g. numEnemies = 0), but at some point it might be handy to be able to reference all the enemies, for example when you want to clear up the level by removing all of them. So you’ll want to have a list of enemies that are currently alive instead (e.g. enemies = {}).

The list of enemies needs to obey certain rules (or invariants, if you want to be fancy). Basically a description of what the list contains at any point in time. We don’t want references to enemies that have long since died, so if an enemy dies it needs to be removed from the list. Once an enemy spawns, it should be added to the list.

Here's how I'd accomplish this:
local enemies = {} --list of enemies, initially empty

function removeFromTable( list, value )
	for i, v in pairs(list) do
		if v == value then
			table.remove(list, i)
			return
		end
	end
end

function  SpawnEnemy( Type )
	local Enemy ...
	table.insert(enemies, Enemy) --update list of enemies to contain this enemy
	local Alive ...
    
	Enemy.Health.Changed:connect(function()
		if Enemy.Health.Value < 0 then
			if Alive then
				-- ...
				removeFromTable(enemies, Enemy) --update list of enemies to no longer contain this enemy
				-- ...
			end
end

It’s really simple to make sure that the list is up to date since you already have code dealing with the enemy spawning and dying. I only changed the three lines where I added comments, and added the function removeFromTable. Now that you have and maintain a list of enemies it’s really easy to count them with the # operator: local numEnemies = #enemies.

Now you can just modify your `while` loop to only spawn new enemies if the current number is below a set maximum:
local maxEnemies = 10

while true do
	wait(1)
	
	if #enemies < maxEnemies then
		local Chance = math.random(1,10)
		if Chance == 7 then
			SpawnEnemy(“Rich Dummy”)
		else
			SpawnEnemy(“Dummy”)
		end
	end
end

Hope this helps, and let me know if you have questions.

2 Likes