Game
Game is a collection of functions and events related to players in the game, rounds of a game, and team scoring.
Class Functions
Class Function Name | Return Type | Description | Tags |
---|---|---|---|
Game.GetLocalPlayer() | Player | Returns the local player. | Client-Only |
Game.GetPlayers([table parameters]) | Array <Player > | Returns a table containing the players currently in the game. An optional table may be provided containing parameters to filter the list of players returned: ignoreDead(boolean), ignoreLiving(boolean), ignoreSpawned(boolean), ignoreDespawned(boolean), ignoreTeams(integer or table of integer), includeTeams(integer or table of integer), ignorePlayers(Player or table of Player), for example: Game.GetPlayers({ignoreDead = true, ignorePlayers = Game.GetLocalPlayer()}) . | None |
Game.FindPlayer(string playerId) | Player | Returns the Player with the given player ID, if they're currently in the game. Otherwise returns nil . | None |
Game.FindNearestPlayer(Vector3 position, [table parameters]) | Player | Returns the Player that is nearest to the given position. An optional table may be provided containing parameters to filter the list of players considered. This supports the same list of parameters as GetPlayers(). | None |
Game.FindPlayersInCylinder(Vector3 position, number radius, [table parameters]) | Array <Player > | Returns a table with all Players that are in the given area. Position's z is ignored with the cylindrical area always upright. An optional table may be provided containing parameters to filter the list of players considered. This supports the same list of parameters as GetPlayers(). | None |
Game.FindPlayersInSphere(Vector3 position, number radius, [table parameters]) | Array <Player > | Returns a table with all Players that are in the given spherical area. An optional table may be provided containing parameters to filter the list of players considered. This supports the same list of parameters as GetPlayers(). | None |
Game.StartRound() | None | Fire all events attached to roundStartEvent. | Server-Only |
Game.EndRound() | None | Fire all events attached to roundEndEvent. | Server-Only |
Game.GetTeamScore(integer team) | integer | Returns the current score for the specified team. Only teams 0 - 4 are valid. | None |
Game.SetTeamScore(integer team, integer score) | None | Sets one team's score. | Server-Only |
Game.IncreaseTeamScore(integer team, integer scoreChange) | None | Increases one team's score. | Server-Only |
Game.DecreaseTeamScore(integer team, integer scoreChange) | None | Decreases one team's score. | Server-Only |
Game.ResetTeamScores() | None | Sets all teams' scores to 0. | Server-Only |
Game.StopAcceptingPlayers() | None | Locks the current server instance to stop accepting new players. Note that players already in the process of joining the server will still be accepted, and Game.playerJoinedEvent may still fire for a short period of time after a call to this function returns. Other new players will be directed to a different instance of the game. | Server-Only |
Game.IsAcceptingPlayers() | boolean | Returns true if the current server instance is still accepting new players. Returns false if the server has stopped accepting new players due to a call to Game.StopAcceptingPlayers() . | None |
Game.TransferAllPlayersToGame(string gameId) | None | Similar to Player:TransferToGame() , transfers all players to the game specified by the passed in game ID. Does not work in preview mode or in games played locally. | Server-Only |
Game.TransferAllPlayersToGame(CoreGameInfo) | None | Similar to Player:TransferToGame() , transfers all players to the game specified by the passed in CoreGameInfo . Does not work in preview mode or in games played locally. | Server-Only |
Game.TransferAllPlayersToGame(CoreGameCollectionEntry) | None | Similar to Player:TransferToGame() , transfers all players to the game specified by the passed in CoreGameCollectionEntry . Does not work in preview mode or in games played locally. | Server-Only |
Game.TransferPlayersToGame(string gameId, Array<Player> players) | None | Similar to Player:TransferToGame() , transfers the specified list of players to the game specified by the passed in game ID. Note that if a party leader is included in the list of players to transfer, the "Play as Party" party setting is ignored, and other party members will only be transferred if also included in the list of players. Does not work in preview mode or in games played locally. | Server-Only |
Game.TransferPlayersToGame(CoreGameInfo, Array<Player> players) | None | Similar to Player:TransferToGame() , transfers the specified list of players to the game specified by the passed in CoreGameInfo . Note that if a party leader is included in the list of players to transfer, the "Play as Party" party setting is ignored, and other party members will only be transferred if also included in the list of players. Does not work in preview mode or in games played locally. | Server-Only |
Game.TransferPlayersToGame(CoreGameCollectionEntry, Array<Player> players) | None | Similar to Player:TransferToGame() , transfers the specified list of players to the game specified by the passed in CoreGameCollectionEntry . Note that if a party leader is included in the list of players to transfer, the "Play as Party" party setting is ignored, and other party members will only be transferred if also included in the list of players. Does not work in preview mode or in games played locally. | Server-Only |
Game.TransferAllPlayersToScene(string sceneName, [table parameters]) | None | Similar to Player:TransferToScene() , transfers all players to the scene specified by the passed in scene name. Does not work in preview mode or in games played locally. The following optional parameters are supported: spawnKey (string) : Spawns the players at a spawn point with a matching key. If an invalid key is provided, the players will spawn at the origin, (0, 0, 0). | Server-Only |
Game.TransferPlayersToScene(string sceneName, Array<Player> players, [table parameters]) | None | Similar to Player:TransferToScene() , transfers the specified list of players to the scene specified by the passed in scene name. Note that if a party leader is included in the list of players to transfer, the "Play as Party" party setting is ignored, and other party members will only be transferred if also included in the list of players. Does not work in preview mode or in games played locally. The following optional parameters are supported: spawnKey (string) : Spawns the players at a spawn point with a matching key. If an invalid key is provided, the players will spawn at the origin, (0, 0, 0). | Server-Only |
Game.GetCurrentGameId() | string | Returns the ID of the current game. When called in preview mode, returns nil if the game has not been published, otherwise returns the published game ID. | None |
Game.GetCurrentSceneName() | string | Returns the name of the current scene. | None |
Events
Event Name | Return Type | Description | Tags |
---|---|---|---|
Game.playerJoinedEvent | Event <Player > | Fired when a player has joined the game and their character is ready. When used in client context it will fire off for each player already connected to the server. | None |
Game.playerLeftEvent | Event <Player > | Fired when a player has disconnected from the game or their character has been destroyed. This event fires before the player has been removed, so functions such as Game.GetPlayers() will still include the player that is about to leave unless using the ignorePlayers filter within the parameters. | None |
Game.roundStartEvent | Event | Fired when StartRound is called on game. | None |
Game.roundEndEvent | Event | Fired when EndRound is called on game. | None |
Game.teamScoreChangedEvent | Event <integer team> | Fired whenever any team's score changes. This is fired once per team who's score changes. | None |
Game.postCameraUpdateEvent | Event | Fired after the camera is updated. It allows Lua code to run after the camera is updated, so a scenario like UI elements positioning themselves to a world location works without a 1 frame lag. | None |
Examples
Example using:
FindNearestPlayer
In this example, the player who is closest to the script's position is made twice as big. All other players are set to regular size.
function Tick()
local allPlayers = Game.GetPlayers()
local nearestPlayer = Game.FindNearestPlayer(script:GetWorldPosition(), {ignoreDead = true})
for _, player in ipairs(allPlayers) do
if player == nearestPlayer then
player:SetWorldScale(Vector3.ONE * 2)
else
player:SetWorldScale(Vector3.ONE)
end
end
Task.Wait(1)
end
See also: Game.GetPlayers | CoreObject.GetWorldPosition | Player.SetWorldScale | Vector3.ONE | CoreLua.Tick | Task.Wait
Example using:
FindPlayer
In this example, when a player joins their ID is saved as a variable. Five seconds later, their ID can be used to fetch that player's object. If they are not found it means they have left the game.
local playerId = nil
local function CheckLater()
local player = Game.FindPlayer(playerId)
if Object.IsValid(player) then
print("Player " .. player.name .. " is still here.")
else
print("Player with id " .. playerId .. " left the game.")
end
end
local function OnPlayerJoined(player)
playerId = player.id
Task.Spawn(CheckLater, 5)
end
Game.playerJoinedEvent:Connect(OnPlayerJoined)
See also: Task.Spawn | Game.playerJoinedEvent | Object.IsValid | Player.name
Example using:
FindPlayersInCylinder
Searches for players in a vertically infinite cylindrical volume. In this example, all players 5 meters away from the script object are pushed upwards. The search is setup to affect players on teams 1, 2, 3, and 4.
function Tick()
local playersInRange = Game.FindPlayersInCylinder(script:GetWorldPosition(), 500, {includeTeams = {1, 2, 3, 4}})
for _, player in ipairs(playersInRange) do
local vel = player:GetVelocity()
vel = vel + Vector3.UP * 250
player:SetVelocity(vel)
end
Task.Wait(0.1)
end
See also: CoreObject.GetWorldPosition | Player.GetVelocity | Vector3.UP | CoreLua.Tick | Task.Wait
Example using:
FindPlayersInSphere
Similar to FindPlayersInCylinder()
, but the volume of a sphere is considered in the search instead. Also note that the player's center is at the pelvis. The moment that point exits the sphere area the effect ends, as the extent of their collision capsules is not taken into account for these searches.
function Tick()
local playersInRange = Game.FindPlayersInSphere(script:GetWorldPosition(), 500)
for _, player in ipairs(playersInRange) do
local vel = player:GetVelocity()
vel = vel + Vector3.UP * 250
player:SetVelocity(vel)
end
Task.Wait(0.1)
end
See also: CoreObject.GetWorldPosition | Player.GetVelocity | Vector3.UP | CoreLua.Tick | Task.Wait
Example using:
GetCurrentGameId
IsAcceptingPlayers
StopAcceptingPlayers
TransferAllPlayersToGame
In this example, players can type the command /reboot
into chat to send all players to a fresh server instance. It's the same game, just another copy of the server. Before transferring the players, we lock the server with StopAcceptingPlayers()
, otherwise some players might reload into the same server instance.
local GAME_ID = Game.GetCurrentGameId()
function OnChatMessage(_, params)
local message = string.lower(params.message)
if message == "/reboot" and Game.IsAcceptingPlayers() then
Game.StopAcceptingPlayers()
Game.TransferAllPlayersToGame(GAME_ID)
end
end
Chat.receiveMessageHook:Connect(OnChatMessage)
See also: Chat.receiveMessageHook
Example using:
GetCurrentSceneName
This example shows how to get the name of the current scene that the player is in.
When a player joins the game, the name of the current scene is printed to the Event Log.
local function OnPlayerJoined(player)
print("Player is in scene: ", Game.GetCurrentSceneName())
end
Game.playerJoinedEvent:Connect(OnPlayerJoined)
See also: Player.TransferToScene
Example using:
GetLocalPlayer
This function can only be called in a client script, as the server does not have a local player. This example prints the names of all players to the upper-left corner of the screen. The local player appears in green, while other player names appear blue. To test this example, place the script under a Client Context. From the point of view of each player, name colors appear different. That's because on each computer the local player is different.
function Tick()
local allPlayers = Game.GetPlayers()
for _, player in ipairs(allPlayers) do
if player == Game.GetLocalPlayer() then
UI.PrintToScreen(player.name, Color.GREEN)
else
UI.PrintToScreen(player.name, Color.BLUE)
end
end
Task.Wait(3)
end
See also: Game.GetPlayers | UI.PrintToScreen | Player.name | Color.GREEN | Task.Wait
Example using:
GetPlayers
This function is commonly used without any options. However, it can be very powerful and computationally efficient to pass a table of optional parameters, getting exactly the list of players that are needed for a certain condition. In this example, when the round ends it prints the number of alive players on team 1, as well as the number of dead players on team 2.
function OnRoundEnd()
local playersAlive = Game.GetPlayers({ignoreDead = true, includeTeams = 1})
local playersDead = Game.GetPlayers({ignoreLiving = true, includeTeams = 2})
print(#playersAlive .. " players on team 1 are still alive.")
print(#playersDead .. " players on team 2 are dead.")
end
Game.roundEndEvent:Connect(OnRoundEnd)
See also: Game.roundEndEvent | CoreLua.print | Event.Connect
Example using:
GetTeamScore
This example checks the score for all four teams and prints them to the screen. Note: Other than in preview mode, the scores will only appear on screen if the script is placed inside a Client Context.
function Tick()
local teamA = Game.GetTeamScore(1)
local teamB = Game.GetTeamScore(2)
local teamC = Game.GetTeamScore(3)
local teamD = Game.GetTeamScore(4)
UI.PrintToScreen("Team A: " .. teamA)
UI.PrintToScreen("Team B: " .. teamB)
UI.PrintToScreen("Team C: " .. teamC)
UI.PrintToScreen("Team D: " .. teamD)
Task.Wait(2.98)
end
See also: UI.PrintToScreen | Task.Wait | CoreLua.Tick
Example using:
ResetTeamScores
In this example, when the round ends team scores are evaluated to figure out which one is the highest, then all scores are reset.
function OnRoundEnd()
-- Figure out which team has the best score
local winningTeam = 0
local bestScore = -1
for i = 1, 4 do
local score = Game.GetTeamScore(i)
if score > bestScore then
winningTeam = i
bestScore = score
end
end
print("Round ended. Team " .. winningTeam .." Resetting scores.")
-- Prepare for the next round
Game.ResetTeamScores()
end
Game.roundEndEvent:Connect(OnRoundEnd)
See also: Game.GetTeamScore | CoreLua.print | Event.Connect
Example using:
SetTeamScore
Team scores don't have to represent things such as kills or points--they can be used for keeping track of and displaying abstract gameplay state. In this example, score for each team is used to represent how many players of that team are within 8 meters of the script.
function Tick()
local pos = script:GetWorldPosition()
for team = 1, 4 do
local teamPlayers = Game.FindPlayersInCylinder(pos, 800, {includeTeams = team})
Game.SetTeamScore(team, #teamPlayers)
end
Task.Wait(0.25)
end
See also: Game.FindPlayersInCylinder | CoreObject.GetWorldPosition | CoreLua.Tick | Task.Wait
Example using:
StartRound
EndRound
In this example, when one of the teams reaches a score of 10 they win the round. Five seconds later a new round starts.
local roundCount = 1
local roundRestarting = false
function OnTeamScoreChanged(team)
local score = Game.GetTeamScore(team)
if score >= 10 and not roundRestarting then
Game.EndRound()
print("Team " .. team .. " wins!")
roundRestarting = true
print("5...")
Task.Wait(1)
print("4...")
Task.Wait(1)
print("3...")
Task.Wait(1)
print("2...")
Task.Wait(1)
print("1...")
Task.Wait(1)
Game.ResetTeamScores()
Game.StartRound()
roundCount = roundCount + 1
roundRestarting = false
print("Starting new round")
end
end
Game.teamScoreChangedEvent:Connect(OnTeamScoreChanged)
See also: Game.GetTeamScore | Event.Connect | Task.Wait | CoreLua.print
Example using:
TransferAllPlayersToScene
In this example, after 10 seconds, all players in the game will be transferred to another scene.
This could be useful after the players in game have defeated a boss, they could all be transferred back to the main lobby.
local bossKilled = true -- Set true for testing
-- If bossKilled is true, after 10 seconds transfer all players
-- to the Lobby scene.
if bossKilled then
Task.Spawn(function()
Game.TransferAllPlayersToScene("Lobby")
end, 10)
end
See also: Player.TransferToScene
Example using:
TransferPlayersToGame
FindPlayer
In this example, a trigger is setup as a teleporter that sends players to a random game. If the player entering the trigger is the leader of a party, then the entire party is transferred to the same game.
local TRIGGER = script:GetCustomProperty("Trigger"):WaitForObject()
function OnBeginOverlap(_, player)
if not player:IsA("Player") then return end
local destinationGame = GetRandomFeaturedGame()
if player.isInParty and player.isPartyLeader then
-- Transfer the whole party
local partyOfPlayers = {}
local partyInfo = player:GetPartyInfo()
for _,playerId in ipairs(partyInfo:GetMemberIds()) do
local p = Game.FindPlayer(playerId)
if p then
table.insert(partyOfPlayers, p)
end
end
Game.TransferPlayersToGame(destinationGame, partyOfPlayers)
else
-- Transfer only the player who entered the trigger
player:TransferToGame(destinationGame)
end
end
function GetRandomFeaturedGame()
local collection = CorePlatform.GetGameCollection("featured")
local rndIndex = math.random(1, #collection)
local entry = collection[rndIndex]
return entry
end
TRIGGER.beginOverlapEvent:Connect(OnBeginOverlap)
See also: Player.GetPartyInfo | PartyInfo.GetMemberIds | CorePlatform.GetGameCollection | Trigger.beginOverlapEvent | CoreObjectReference.WaitForObject
Example using:
TransferPlayersToScene
FindPlayersInCylinder
In this example, a group teleporter periodically sends any players who are standing inside of it to another scene. It then spawns a VFX at the location of the teleport, providing feedback to other players who may be watching nearby.
local SCENE_NAME = script:GetCustomProperty("SceneName")
local VFX_TEMPLATE = script:GetCustomProperty("VFX")
local PERIOD = 120 -- Two minutes
local RADIUS = 500 -- 5 meters
while true do
Task.Wait(PERIOD)
local pos = script:GetWorldPosition()
local players = Game.FindPlayersInCylinder(pos, RADIUS)
if #players > 0 then
Game.TransferPlayersToScene(SCENE_NAME, players)
World.SpawnAsset(VFX_TEMPLATE, {position = pos})
end
end
See also: World.SpawnAsset | CoreObject.GetCustomProperty | Task.Wait
Example using:
playerJoinedEvent
playerLeftEvent
Events that fire when players join or leave the game. Both server and client scripts detect these events. In the following example teams are kept balanced at a ratio of 1 to 2. For example if there are 6 players two of them will be on team 1 and the other four will be on team 2.
local BALANCE_RATIO = 1 / 2
local playerCount = 0
local team1Count = 0
local team2Count = 0
function OnPlayerJoined(player)
player.team = NextTeam()
end
function OnPlayerLeft(player)
playerCount = 0
team1Count = 0
team2Count = 0
local allPlayers = Game.GetPlayers()
for _, p in ipairs(allPlayers) do
if p ~= player then
p.team = NextTeam()
end
end
end
function NextTeam()
local team = 1
if playerCount == 0 then
team1Count = 1
elseif team2Count == 0 then
team2Count = 1
team = 2
else
local ratio = team1Count / team2Count
if ratio < BALANCE_RATIO then
team1Count = team1Count + 1
else
team2Count = team2Count + 1
team = 2
end
end
playerCount = playerCount + 1
return team
end
Game.playerJoinedEvent:Connect(OnPlayerJoined)
Game.playerLeftEvent:Connect(OnPlayerLeft)
See also: Player.team | Game.GetPlayers | Event.Connect
Example using:
postCameraUpdateEvent
In this example, the postCameraUpdateEvent is used over a Tick function as it allows Lua code to run after the camera is updated, which removes the lag from UI elements being positioned to a world location.
-- Client context script
local TARGET = script:GetCustomProperty("Target"):WaitForObject()
local IMAGE = script:GetCustomProperty("Image"):WaitForObject()
local function UpdateImage()
local pos = UI.GetScreenPosition(TARGET:GetWorldPosition())
IMAGE.x = pos.x
IMAGE.y = pos.y
end
-- Uncomment the below code and comment out the postCameraUpdateEvent line to see
-- the difference between the Tick updating the UI compared to the post camera event.
--[[
function Tick()
UpdateImage()
end
--]]
Game.postCameraUpdateEvent:Connect(UpdateImage)
See also: CoreObjectReference.GetWorldPosition | UI.GetScreenPosition | CoreObject.GetCustomProperty | Event.Connect
Example using:
roundEndEvent
Several operations need to be made when rounds start and end. In this example, when the game ends it transitions to a "round ended" state for three seconds, then respawns all players to spawn points. The advantage of using events is that the different scripts can be separated from each other to improve organization of the project. The condition for ending the round is set here as one team reaching 5 points and can be located in one script. Meanwhile the various outcomes/cleanups can be broken up into different scripts in a way that makes the most sense per game, all listening to the roundEndEvent
.
local gameState = "PLAYING"
function OnRoundEnd()
gameState = "END"
print("Round ended. Team " .. winningTeam .. " won!")
-- Waits for 3 seconds then continues
Task.Wait(3)
-- Respawn all the players
local allPlayers = Game.GetPlayers()
for _, player in ipairs(allPlayers) do
player:Spawn()
end
Game.ResetTeamScores()
gameState = "LOBBY"
end
Game.roundEndEvent:Connect(OnRoundEnd)
function Tick()
if gameState == "PLAYING" then
local scoreObjective = 5
if Game.GetTeamScore(1) == scoreObjective then
winningTeam = 1
Game.EndRound()
elseif Game.GetTeamScore(2) == scoreObjective then
winningTeam = 2
Game.EndRound()
end
end
end
See also: Game.EndRound | Player.Spawn | CoreLua.print | Task.Wait | Event.Connect
Example using:
roundStartEvent
Several functions and events in the Game
namespace are convenient for controlling the flow of a game. In this example, the game requires two players to join. It begins in a lobby state and transitions to a playing state when there are enough players.
local gameState = "LOBBY"
print("Waiting for 2 players to join...")
function OnRoundStart()
gameState = "PLAYING"
print("New round starting...")
end
Game.roundStartEvent:Connect(OnRoundStart)
function Tick()
if gameState == "LOBBY" then
-- The condition for starting a round
local playerCount = #Game.GetPlayers()
if playerCount >= 2 then
Game.StartRound()
end
end
end
See also: Game.StartRound | CoreLua.print | Event.Connect
Example using:
teamScoreChangedEvent
IncreaseTeamScore
DecreaseTeamScore
In this example, when a player jumps their team gains 1 point and when they crouch their team loses 1 point. The OnTeamScoreChanged
function is connected to the event and prints the new score to the Event Log each time they change.
function OnTeamScoreChanged(team)
local score = Game.GetTeamScore(team)
print("Score changed for team " .. team .. ", new value = " .. score)
end
Game.teamScoreChangedEvent:Connect(OnTeamScoreChanged)
function HandlePlayerJumped(player)
Game.IncreaseTeamScore(player.team, 1)
end
function HandlePlayerCrouched(player)
Game.DecreaseTeamScore(player.team, 1)
end
local playersJumping = {}
local playersCrouching = {}
function Tick()
local allPlayers = Game.GetPlayers()
for _, player in ipairs(allPlayers) do
-- Jump
if player.isJumping and player.isJumping ~= playersJumping[player] then
HandlePlayerJumped(player)
end
playersJumping[player] = player.isJumping
-- Crouch
if player.isCrouching and not player.isJumping and player.isCrouching ~= playersCrouching[player] then
HandlePlayerCrouched(player)
end
playersCrouching[player] = player.isCrouching
end
end
See also: Game.GetTeamScore | Player.isJumping | CoreLua.print