Spawning Enemies

Spawning Enemies

Now that players have a working ship, it’s time to add some randomly spawning enemies for players to dodge. Double-check the walls of your arena to make sure they don’t overlap with the baseplate. If the walls do overlap, enemies will try to spawn inside of the walls where they can’t be shot.

Create the Enemy

The first task is to create an enemy object to make multiple copies of within ServerStorage. ServerStorage is used to hold objects scripts can make copies of when needed.

  1. Inside of ServerStorage, add a Folder renamed Enemies.
  2. In the Enemies folder, add a Sphere part named EnemyBall.
  3. With EnemyBall selected, check CustomPhysicalProperties and set the Friction value to 0. This will let the balls slide around forever on the arena’s baseplate.
  4. In the Workspace, add a Folder named Enemies (the game will have two folders named Enemies). This folder will store all spawned enemies.

Coding the Enemy Behavior

Once again is the question of which type of script object to use. Enemies should appear the same to all players, and players shouldn’t be able to control them.

  1. In ServerScriptService add a new Script named EnemyHandler.

Create the Variables

Variables like how many enemies to spawn should be created as constant variables at the top of the script. This makes it easier to tweak the game later without rewriting a bunch of code. The script will need numeric constant values for each of the following:

  • Number of enemies
  • Size of a safe zone to make spawning a little safer
  • Max speed of the enemies
  • Amount of time a player has to wait until respawning

You’ll also need a variable to get to ServerStorage to access the EnemyBall created earlier.

  1. In EnemyHandler, add a comment for the script and the variables discussed above.

Writing the Function to Spawn Enemies

To create the number of enemies set in ENEMY_COUNT, the script will use a for loop. The for loop will go through all of the same code for each enemy until all enemies are created.

  1. Add a function named spawnEnemies() with a parameter named count for the number of enemies to spawn.
  1. Add a local variable for the baseplate’s size. It will be used to determine where to spawn the enemies.
  1. Add a For loop that will keep running until the right number of enemy copies are made.
  1. Inside the for loop, create a random starting place and a random speed for each enemy.
  1. Call the spawnEnemies() function at the very end of the script, using ENEMY_COUNT as a parameter.

Enemy and Player Collisions

While enemies are created in the game, they don’t do anything to the player. To give players a challenge, every time they hit an enemy, their character will explode and be taken out of the game for a short time.

Check if Player Hit an Enemy

  1. In the same EnemyHandler script, above spawnEnemies(), add a function named onTouched(), with an parameter named other. The other part is what touched the enemy.
-- This is fired every time as enemy touches another part
local function onTouched(other)

  1. Check if the other part is one of the parts in the player’s ship.
local function onTouched(other)
    if other.Name == "HumanoidRootPart" or other.Name == "Blaster" then


Make the Player Respawn

Within the if statement, code what should happen to any player that is found touching an enemy.

  1. Create a local variable to store the parent of the other part.
local function onTouched(other)
    if other.Name == "HumanoidRootPart" or other.Name == "Blaster" then
        local character = other.Parent
  1. Move the player character to ReplicatedStorage to temporarily take them out of the game.
local function onTouched(other)
	if other.Name == "HumanoidRootPart" or other.Name == "Blaster" then
		local character = other.Parent
		-- Hide the player during the explosion
		character.Parent = game:GetService("ReplicatedStorage")
  1. Spawn an Explosion where the player was.
character.Parent = game:GetService("ReplicatedStorage")
-- Fire explosion where the player was
local explosion = Instance.new('Explosion', workspace)
explosion.Position = character:GetPrimaryPartCFrame().p
  1. After creating the explosion, make the player wait to be respawned for the amount of time set in RESPAWN_DURATION at the top of the script.
local explosion = Instance.new('Explosion', workspace)
explosion.Position = character:GetPrimaryPartCFrame().p

  1. After the wait(), bring the character back into the game workspace and stop their previous movement entirely.

-- Reveal the character after they are knocked out and stop their movement
character.Parent = workspace
character.HumanoidRootPart.Velocity = Vector3.new(0,0,0)
character.HumanoidRootPart.VectorForce.Force = Vector3.new(0,0,0)

Finish the Code

Go back to the for loop where you created the directions for spawning enemies. The collision code needs to connect to the Enemy’s Touch event.

  1. In the spawnEnemies() function, after enemy.Velocity, connect the onTouched() function to the enemy’s Touched event.
local function spawnEnemies(count)
	local baseplateSize = workspace.Arena.Baseplate.Size

	-- Loop until we have as many enemy as we want
	for i = 1, count do
		-- Clone our default enemy
		local enemy = ServerStorage.Enemies.EnemyBall:Clone()
		enemy.Parent = workspace.Enemies
		-- Assign a random position in the arena
		local randomX = math.random(baseplateSize.X / -2 - SAFE_ZONE_SIZE, baseplateSize.X / 2 + SAFE_ZONE_SIZE)
		local randomZ = math.random(baseplateSize.Z / -2 - SAFE_ZONE_SIZE, baseplateSize.Z / 2 + SAFE_ZONE_SIZE)
		enemy.Position = Vector3.new(randomX , 9, randomZ)
		-- Assign a random velocity to the enemy
		local randomVX = math.random(-1 * MAX_ENEMY_SPEED, MAX_ENEMY_SPEED)
		local randomVZ = math.random(-1 * MAX_ENEMY_SPEED, MAX_ENEMY_SPEED)
		enemy.Velocity = Vector3.new(randomVX, 0, randomVZ)
		-- Make sure every time the enemy hits something,
		-- it will check if it hit the player

  1. Playtest your game to make sure the explosion is working. If the RESPAWN_DURATION feels too long, change the constant’s value at the top of the script. If the initial enemy count feels too low, you can change that too!

These documents are licensed by Roblox Corporation under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Roblox, Powering Imagination, and Robux are trademarks of Roblox Corporation, registered in the United States and other countries.

Previous Adding Player Controls Next Ship Blasters