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.
- Inside of ServerStorage, add a Folder renamed Enemies.
- In the Enemies folder, add a Sphere part named EnemyBall.
- 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.
- 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.
- 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.
- 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.
- Add a function named
spawnEnemies()with a parameter named count for the number of enemies to spawn.
- Add a local variable for the baseplate’s size. It will be used to determine where to spawn the enemies.
- Add a For loop that will keep running until the right number of enemy copies are made.
- Inside the for loop, create a random starting place and a random speed for each enemy.
- Call the
spawnEnemies()function at the very end of the script, using
ENEMY_COUNTas 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
- 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) end
- 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 end end
Make the Player Respawn
Within the if statement, code what should happen to any player that is found touching an enemy.
- 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 end end
- 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") end end
- 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
- After creating the explosion, make the player wait to be respawned for the amount of time set in
RESPAWN_DURATIONat the top of the script.
local explosion = Instance.new('Explosion', workspace) explosion.Position = character:GetPrimaryPartCFrame().p wait(RESPAWN_DURATION)
- After the
wait(), bring the character back into the game workspace and stop their previous movement entirely.
wait(RESPAWN_DURATION) -- 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.
- In the
enemy.Velocity, connect the
onTouched()function to the enemy’s
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 enemy.Touched:Connect(onTouched) end end
- Playtest your game to make sure the explosion is working. If the
RESPAWN_DURATIONfeels 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 Top-Down Camera Next Ship Blasters