title | description | next | prev |
---|---|---|---|
Managing Players |
Create a battle royale experience in Roblox Studio. Write scripts that handle player spawning and equipment. |
/education/battle-royale-series/timers-and-events |
/education/battle-royale-series/coding-the-game-loop |
With the game loop coded, it's time to start adding features into it. During a match, players can come and go. Because of this, code is needed for tasks like sending players into a match and keeping track of active players. To manage these tasks, create a module script named PlayerManager.
This script will start a function to send players into the arena with a weapon and be expanded later in the series.
Because the player manager includes functions used by other scripts, it'll be a module script.
-
In ServerStorage > ModuleScripts, add a new module script named PlayerManager. Then, rename the module table to match the script name and add comments for local and module functions.
local PlayerManager = {} -- Local Functions -- Module Functions return PlayerManager
-
Add local variables for the following:
Services:
- Players - Know what players have joined or left the game.
- ServerStorage - Storage for player weapons.
Map and Player Variables:
- Lobby Spawn, Arena Folder, and Arena Spawn Folder - Used to teleport players to different areas.
- An Array of Active Players - Keeps track of players currently in a game.
local PlayerManager = {} -- Services local Players = game:GetService("Players") local ServerStorage = game:GetService("ServerStorage") -- Map Variables local lobbySpawn = workspace.Lobby.StartSpawn local arenaMap = workspace.Arena local spawnLocations = arenaMap.SpawnLocations -- Player Variables local activePlayers = {} -- Local Functions -- Module Functions return PlayerManager
-
Create a module function named
sendPlayersToMatch()
with a test print inside.-- Local Functions -- Module Functions function PlayerManager.sendPlayersToMatch() print("Sending players to match") end return PlayerManager
Right now, there's multiple spawn locations, meaning that players spawn at a random one when joining the game. To ensure players spawn in the lobby, change the player's RespawnLocation
property.
-
Create a new local function named
onPlayerJoin()
with a parameter ofplayer
. In that function, set the player's respawn location to the lobby spawn variable made earlier.-- Local Functions local function onPlayerJoin(player) player.RespawnLocation = lobbySpawn end
-
Add an events section beneath your module function. Then, connect
onPlayerJoin()
to Player Service'sPlayerAdded
event.-- Module Functions function PlayerManager.sendPlayersToMatch() print("Sending players to match") end -- Events Players.PlayerAdded:Connect(onPlayerJoin)
Now the modules can be connectd and tested. With the PlayerManager created, require it so that the code in that module script can then run and send players to the lobby.
-
Go back to MatchManager and create variables for the following:
- ServerStorage service.
- ModuleScripts folder, child of ServerStorage.
- PlayerManager module script, child of moduleScripts.
local MatchManager = {} -- Services local ServerStorage = game:GetService("ServerStorage") -- Module Scripts local moduleScripts = ServerStorage:WaitForChild("ModuleScripts") local playerManager = require(moduleScripts:WaitForChild("PlayerManager")) function MatchManager.prepareGame() playerManager.sendPlayersToMatch() end return MatchManager
-
Use a local server with at least the minimum players to test. Confirm that you can see the following:
- All players spawn in the Lobby.
- The print statement from PlayerManager appears in the Output Window.
-
Once finished, click Cleanup to shut down the server.
At this point, parts of the script aren't working as intended, try one of the following below.
- Check the name of parts such as the Arena, or the location of Lobby > StartSpawn, especially if you named them differently than instructed in the lesson.
- Make sure that modules are required in each script using the
require()
function and correctly spelled.
Now that players spawn in the lobby, teleport them into a match once the intermission is over. Change the player's RespawnLocation
to a spawn location in the arena using a function in the Player object called ReloadCharacter()
.
-
Go to the PlayerManager script, below
onPlayerJoin()
, add a new local function namedpreparePlayer()
. Include two parameters:player
andwhichSpawn
, the spawn location to send them to.local activePlayers = {} -- Local Functions local function onPlayerJoin(player) player.RespawnLocation = lobbySpawn end local function preparePlayer(player, whichSpawn) end -- Module Functions function PlayerManager.sendPlayersToMatch() print("Sending players to match") end
-
Set the player's respawn location to
whichSpawn
.local function preparePlayer(player, whichSpawn) player.RespawnLocation = whichSpawn end
-
Force the character to reload, using
LoadCharacter()
, and the player will respawn using their newly assigned location.local function preparePlayer(player, whichSpawn) player.RespawnLocation = whichSpawn player:LoadCharacter() end
Make sure each player gets teleported to a different spawn location in the arena by using a for
loop to iterate through the active players array. Using a for
loop allows you to go through every value in the players array, allowing the script to adapt to a variety of player numbers.
-
In the
sendPlayersToMatch()
function, use a variable to create an array of all the arena spawn locations by getting the children of the Arena > SpawnLocations folder.--Module Functions function PlayerManager.sendPlayersToMatch() local arenaSpawns = spawnLocations:GetChildren() end
-
Add the
for
loop below to get an array of all players and then iterate through each of them. To get players, type:Players:GetPlayers()
.function PlayerManager.sendPlayersToMatch() local arenaSpawns = spawnLocations:GetChildren() for playerKey, whichPlayer in Players:GetPlayers() do end end
When the game runs, it needs to identify which users are playing so they can be spawned in the arena. At the start of a round, every player will be tracked in an array of active players. That array will be used for different functions, such as teleporting or assigning weapons, ensuring that players still in the lobby during a round aren't affected.
-
In the for loop, use
Library.table.insert()
, using the two parameters for theactivePlayers
array and the player to add.function PlayerManager.sendPlayersToMatch() local arenaSpawns = spawnLocations:GetChildren() for playerKey, whichPlayer in Players:GetPlayers() do table.insert(activePlayers,whichPlayer) end end
-
To get a spawn location from the arena, create a variable named
spawnLocation
and set it to the first index in thearenaSpawns
table.for playerKey, whichPlayer in Players:GetPlayers() do table.insert(activePlayers,whichPlayer) local spawnLocation = arenaSpawns[1] end
-
Call
preparePlayer()
and pass inwhichPlayer
andspawnLocation
. Then, since that spawn location was used, remove it from the table so the next player will get a different spawn.for playerKey, whichPlayer in Players:GetPlayers() do table.insert(activePlayers,whichPlayer) local spawnLocation = arenaSpawns[1] preparePlayer(whichPlayer, spawnLocation) table.remove(arenaSpawns, 1) end
-
Test on a local server that players are sent to the arena. The players will continue to respawn at the same location because the code to send them back to the lobby isn't yet in place.
At this point, you didn't see the intended results, try one of the following below.
- In
GetPlayers()
, make sure there are two closing parentheses, such asClass.Players.GetPlayers(|Players:GetPlayers())
in the statement. - Check the series of function calls in the module scripts. For example,
matchManager.prepareGame()
should callplayerManager.sendPlayersToMatch()
.
When a round starts, each player in the arena will be provided a weapon to use.
Player weapons will be a tool. While any tool in Roblox can be used, we've provided a sample sword to start.
-
Import the weapon from the Toolbox, or create your own (see
Get ToolClass.Tool|Tools
). -
Place the weapon into ServerStorage. If you're creating your own tool, make sure the tool is named Weapon, since that'll be used in later scripts.
Now that the tool is in storage, work on a script to go through the active player array and provide each user that tool.
-
In PlayerManager, add a variable named
playerWeapon
for the Weapon in ServerStorage.-- Map Variables local lobbySpawn = workspace.Lobby.StartSpawn local arenaMap = workspace.Arena local spawnLocations = arenaMap.SpawnLocations -- Player Variables local activePlayers = {} local playerWeapon = ServerStorage.Weapon
-
In
preparePlayer()
, paste the following code to get the player's character.It's possible that a player's character isn't loaded when the game starts. Adding the extra wait ensures that if a character isn't immediately available, the script will wait and not cause an error.local function preparePlayer(player, whichSpawn) player.RespawnLocation = whichSpawn player:LoadCharacter() local character = player.Character or player.CharacterAdded:Wait() end
-
Create a new variable named sword and use the
Clone()
function to create a copy of the weapon in ServerStorage. Then, parent the sword to the player's character.local function preparePlayer(player, whichSpawn) player.RespawnLocation = whichSpawn player:LoadCharacter() local character = player.Character or player.CharacterAdded:Wait() local sword = playerWeapon:Clone() sword.Parent = character end
-
Test on a local server to confirm that every player gets a tool when sent to the arena. Keep in mind, if you continue testing, the intermission will keep restarting and so players will respawn every few seconds. This will be resolved in the next lesson.
Below are completed scripts to double check your work.
-- Services
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
-- Module Scripts
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local matchManager = require(moduleScripts:WaitForChild("MatchManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
while true do
repeat
task.wait(gameSettings.intermissionDuration)
print("Restarting intermission")
until #Players:GetPlayers() >= gameSettings.minimumPlayers
print("Intermission over")
task.wait(gameSettings.transitionTime)
matchManager.prepareGame()
end
local MatchManager = {}
-- Services
local ServerStorage = game:GetService("ServerStorage")
-- Module Scripts
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local playerManager = require(moduleScripts:WaitForChild("PlayerManager"))
function MatchManager.prepareGame()
playerManager.sendPlayersToMatch()
end
return MatchManager
local PlayerManager = {}
-- Services
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
-- Map Variables
local lobbySpawn = workspace.Lobby.StartSpawn
local arenaMap = workspace.Arena
local spawnLocations = arenaMap.SpawnLocations
-- Player Variables
local activePlayers = {}
local playerWeapon = ServerStorage.Weapon
-- Local Functions
local function onPlayerJoin(player)
player.RespawnLocation = lobbySpawn
end
local function preparePlayer(player, whichSpawn)
player.RespawnLocation = whichSpawn
player:LoadCharacter()
local character = player.Character or player.CharacterAdded:Wait()
local sword = playerWeapon:Clone()
sword.Parent = character
end
-- Module Functions
function PlayerManager.sendPlayersToMatch()
print("Sending players to match")
local arenaSpawns = spawnLocations:GetChildren()
for playerKey, whichPlayer in Players:GetPlayers() do
table.insert(activePlayers,whichPlayer)
local spawnLocation = arenaSpawns[1]
preparePlayer(whichPlayer, spawnLocation)
table.remove(arenaSpawns, 1)
end
end
--events
Players.PlayerAdded:Connect(onPlayerJoin)
return PlayerManager