# Big long article
In previous courses, you’ve used events to create playable scenes. Most recently, in [Deadly Arena], you’ve made a board of tumbling platforms above a deadly lava floor.
Now it’s time to make something a little more like a real game. You’ll create a of scripted platforms, but this time players should earn points for surviving for longer, and should lose all their points when they die. The platforms should also reset, so that players can play the game more than once.
[footage of players playing on the finished article]
You’ll need to use some new events and features to achieve this.
Setting Up
Before you start coding, you’ll need to set the scene for your game.
Insert a Part for the platform you’ll be scripting - you’ll duplicate this later once you’ve written the code. Make sure it has an appropriate name, like ‘DisappearingPlatform’.
Put a spawn point just above it so that players can jump down to the platform to start the game, and make sure it’s big enough for more than one player to stand on.
[image of part and spawn point in place]
Players need to die when they fall off a platform. You can use the deadly lava floor from [Deadly Arena] in your game to achieve this - or you can just remove the floor entirely and let gravity do the job for you.
How do you award points to players? Even if you made a ‘points’ property for each player, you’d still need a way to display them. Fortunately, Roblox has an easy system for showing points for players called the Leaderboard.
[image of leaderboards with points stat visible]
When you set a player’s points through the Leaderboard, it’ll show up on the right side of the screen in the game. Later, you’ll learn better ways to display all kinds of information through user interfaces, but for now the Leaderboard is the simplest way of making a scoring system in Roblox you can actually see in-game.
Create a Script in the Workspace called SetupLeaderboard. You’ll use this to set up the Leaderboard for each player that joins your game.
Listening for Players
You need an event that will fire when a player joins the game, so that you can set up the points each time and ensure every player has their points displayed. Fortunately, the Players service has an event called PlayerAdded which does exactly that.
A service is an object which exists at the top level of your Roblox game, like Workspace and Lighting. They perform a range of useful functions. The Players service contains a list of all the players in the game, along with other related information. Each player in your game has a corresponding Player object in the Players service.
[image of players in the Players service in the Explorer]
You can access services with the GetService function in the game object. GetService takes a name for a service and returns the service with that name. If it doesn’t exist yet, it’ll create it and then return it.
game is a variable accessible from anywhere. It contains all the things you see in the Explorer window.
Create a variable for the Players service using the GetService function.
Create a function called ‘onPlayerAdded’ with a parameter for the player, so the PlayerAdded event can pass the player to the function when it fires.
Connect the onPlayerAdded function to the PlayerAdded event.
local Players = game:GetService("Players")
local function onPlayerAdded(player)
end
Players.PlayerAdded:Connect(onPlayerAdded)
Just like the Touched event in [Deadly Arena], the PlayerAdded event calls any function connected to it with an argument. In this case, the argument is the player that was added to the game. You’ll need to use the player that was added in your code, so you need to have the parameter to make sure you can access it.
Leaderstats
Time to set up the Leaderboard. To create a points entry in the Leaderboard for a given player, all you need to do is create a new folder in their Player object called ‘leaderstats’, and put the points value in there. Roblox automatically reads and displays any values you put in that folder.
You can create a new folder using Instance.new, which is a special function that can create objects if you give it the name of the type of the object you want. In this case, you want a folder, so you’d write Instance.new(“Folder”).
Create a new folder variable called leaderstats using Instance.new.
Set the Name property of the folder to “leaderstats”.
Put the folder in the Player object by setting the Parent property to player.
local Players = game:GetService("Players")
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
end
Players.PlayerAdded:Connect(onPlayerAdded)
Points Value
The Leaderboard system reads any IntValue objects in the leaderstats folder and will display whatever it finds - so you’ll need to store the points as an IntValue.
An IntValue is a type of object that stores a whole number (an integer - int for short) and a name to associate with it. Numbers which need to be visible and accessible outside of a given script are typically stored this way.
Create a new IntValue variable called ‘points’ using Instance.new.
Set the Name property of points to “Points”.
Set the Value property of points to 0.
Put the points object in the leaderstats folder by setting the Parent property to leaderstats.
local Players = game:GetService("Players")
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local points = Instance.new("IntValue")
points.Name = "Points"
points.Value = 0
points.Parent = leaderstats
end
Players.PlayerAdded:Connect(onPlayerAdded)
Test your game now, and you should see the Leaderboard appear in the top right with the names of your players and a points score next to them.
If you look at the Explorer, you can see that the leaderstats folder is inside the Player object for your player, with the Points object being inside that.
[image of the Explorer showing this]
Scripting the Platform
Next up: making the platforms disappear and award points when you step on them. You should already have inserted a part to act as your platform.
Insert a Script into the platform part.
Create a variable for the platform with script.Parent.
Create a function called ‘onTouched’ with a parameter called ‘otherPart’.
Connect the onTouched function to the platform’s Touched event.
Use a Boolean variable to debounce the onTouched function.
local platform = script.Parent
local isTouched = false
local function onTouched(otherPart)
if not isTouched then
isTouched = true
isTouched = false
end
end
platform.Touched:Connect(onTouched)
The code for the platform behavior will go between the isTouched = true assignment and the isTouched = false assignment.
Making the Platform Disappear
The Transparency and CanCollide properties can be used to make the platform disappear. You can use the code from the [Simple Trap] course to achieve this.
Create a for loop and use the iterator to set the Transparency property of the platform.
Set the CanCollide property of the platform to false, then wait for 20 seconds.
Set the Transparency and CanCollide properties back to their default values.
local platform = script.Parent
local isTouched = false
local function onTouched(otherPart)
if not isTouched then
isTouched = true
for i = 0, 1 do
platform.Transparency = i/10
wait(0.1)
end
platform.CanCollide = false
wait(20)
platform.Transparency = 0
platform.CanCollide = true
isTouched = false
end
end
platform.Touched:Connect(onTouched)
Getting the Player
In order to give a point to the player when they step on the platform, you need to somehow get their Player object out of the otherPart parameter in the onTouched function, as the Player object is where we put the leaderstats folder.
The [Deadly Arena] course covered how every player has a Character model, and a part of this model - e.g. the right leg - is what will actually touch the platform and be passed as an argument to the onTouched function. If a player touches a platform, the parent of the part that touched the platform will therefore be a Character.
So how do you get the Player object from the Character? The Players service has a GetPlayerFromCharacter function that takes a Character as an argument and returns a corresponding Player object. It returns nil if the player doesn’t exist, so it’s important to check the result in case you later cause an error.
Use the GetPlayerFromCharacter function to get the Player object from the parent of the part that touched the platform.
Check that the result exists using an if statement before proceeding.
local platform = script.Parent
local isTouched = false
local Players = game:GetService("Players")
local function onTouched(otherPart)
if not isTouched then
isTouched = true
local character = part.Parent
if character then
local player = Players:GetPlayerFromCharacter(character)
if player then
for i = 0, 1 do
platform.Transparency = i/10
wait(0.1)
end
platform.CanCollide = false
wait(20)
platform.Transparency = 0
platform.CanCollide = true
end
end
isTouched = false
end
end
platform.Touched:Connect(disappear)
Organizing the Script
At this point, the code in the onTouched function is getting unwieldy and difficult to read. Before carrying on, it would be best to split it up and organize it better by creating functions to include the code for each part of the platform’s behavior.
The code for making the platform disappear and reappear is straightforward to move out of the onTouched function, but the code for getting the player object would require access to the otherPart parameter, and would need to provide the result of attempting to get the player object from it. This means we’ll need to create a function with a parameter and a return statement.
Return Statements
A return statement passes back a value from a function, to be used where the function was called.
It’s how you make your own functions which can do the same sort of thing as e.g. GetPlayerFromCharacter, where the function produces a value you can use.
You just have to write return, followed by the thing you want to pass back.
Move the code for making the platform disappear into its own function.
Move the code for making the platform reappear into its own function.
Move the code for getting the Player object from the otherPart parameter into its own function.
local platform = script.Parent
local isTouched = false
local Players = game:GetService("Players")
local function getPlayerFromPart(part)
local character = part.Parent
if character then
local player = Players:GetPlayerFromCharacter(character)
return player
end
end
local function disappear()
for i = 0, 1 do
platform.Transparency = i/10
wait(0.1)
end
platform.CanCollide = false
end
local function reappear()
platform.Transparency = 0
platform.CanCollide = true
end
local function onTouched(otherPart)
if not isTouched then
isTouched = true
local player = getPlayerFromPart(otherPart)
if player then
disappear()
wait(20)
reappear()
end
isTouched = false
end
end
platform.Touched:Connect(onTouched)
This has all made the script a bit longer, but it’s much easier to read and understand now. It’s important when coding to be efficient, but it’s rarely a good idea to prioritise brevity over clarity.
Awarding a Point
Once you have a Player object in your code, you can add a point to the player’s Points value when they step on the platform. In Lua, you add a number to a variable through assigning it the same way you would assign any other value.
Create a variable called points for the player’s Points object.
Add 1 to the Value property of the points variable.
local platform = script.Parent
local isTouched = false
local Players = game:GetService("Players")
local function getPlayerFromPart(part)
local character = part.Parent
if character then
local player = Players:GetPlayerFromCharacter(character)
return player
end
end
local function disappear()
for i = 0, 1 do
platform.Transparency = i/10
wait(0.1)
end
platform.CanCollide = false
end
local function reappear()
platform.Transparency = 0
platform.CanCollide = true
end
local function onTouched(otherPart)
if not isTouched then
isTouched = true
local player = getPlayerFromPart(otherPart)
if player then
local points = player.leaderstats.Points
points.Value = points.Value + 1
disappear()
wait(20)
reappear()
end
isTouched = false
end
end
platform.Touched:Connect(onTouched)
Test your code now, and you should find that you get a point on the Leaderboard when you step on the platform.
Listening for Characters
Currently, players who die in the game still get to keep all their points, so there’s no incentive to survive for longer. A player’s points should reset to 0 when they die.
The lava floor script from [Deadly Arena] used the Humanoid inside the player’s Character model to kill them, since the Humanoid contains information about a player’s health. Humanoid also has a Died event, which you can use here to find out when a player has died so that you can reset their points.
In order to do this, first you’ll need to get the Character for the player. The Character is only added to the game after the Player object has been loaded. Use the CharacterAdded event in the Player object to listen for when the Character is ready to use.
Create a function called ‘onCharacterAdded’, with two parameters: one for the character, one for the player.
Connect an anonymous function to the CharacterAdded event with a parameter for the character.
In the body of the anonymous function, call the onCharacterAdded function with the character as the first argument and the player as the second.
local players = game:GetService("Players")
local function onCharacterAdded(character, player)
end
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local points = Instance.new("IntValue")
points.Name = "Points"
points.Value = 0
points.Parent = leaderstats
player.CharacterAdded:Connect(function(character)
onCharacterAdded(character, player)
end)
end
players.PlayerAdded:Connect(onPlayerAdded)
Why the second argument for onCharacterAdded, and why the strange function for the CharacterAdded event?
You need to have the Player object later in your code, because you’ll need to get the Points value from the player’s leaderstats folder. But the CharacterAdded event doesn’t provide the Player object to the function that connects to it - it only provides the Character.
Ideally, you’d want the CharacterAdded event to call a function which then calls the onCharacterAdded function with an extra player argument for the Player object. Otherwise, if you connected the onCharacterAdded function directly to the event, you wouldn’t be able to pass it the Player object. Here, an anonymous function is used to create this ‘wrapper’ function.
Anonymous Functions
This is a function with no name, which can be treated as a value.
It’s used here to efficiently ‘wrap’ a call to the function you actually want to run - i.e. onCharacterAdded - so that we can call it with a bonus argument for the player.
A wrapper function like this doesn’t need a name, so being able to put it directly into the parentheses for the event connection saves space and keeps things simple.
Listening for the Humanoid
The Died event you’re looking for is in the Humanoid, inside the Character object. You need to wait for the Humanoid object to be loaded in first - the Humanoid won’t necessarily be there just because the Character model is present. If you try to connect to the event before the Humanoid has loaded, you’ll cause an error.
Every object in Roblox has a WaitForChild function, which looks for an object with a given name and stops the code until it finds it. It takes the name of the object you’re looking for as a String. You can use it here to get the Humanoid safely before connecting to the Died event.
It’s best to connect to the Died event using an anonymous function as a wrapper, so that you can pass the player through and use it later to reset the points.
Create a variable for the Humanoid, and assign to it the result of calling WaitForChild on the character with the argument ‘Humanoid’.
Create a function called ‘onCharacterDied’, with a parameter for the player.


Connect an anonymous function to the Died event of the Humanoid variable.
In the body of the anonymous function, call the onCharacterDied function with the player as an argument.
local players = game:GetService("Players")
local function onCharacterDied(player)
end
local function onCharacterAdded(character, player)
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Connect(function()
onCharacterDied(player)
end)
end
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local points = Instance.new("IntValue")
points.Name = "Points"
points.Value = 0
points.Parent = leaderstats
player.CharacterAdded:Connect(function(character)
onCharacterAdded(character, player)
end)
end
players.PlayerAdded:Connect(onPlayerAdded)
Resetting the Points
Finally, you can reset the player’s points in the onCharacterDied function using the player parameter.
Create a variable called ‘points’ for the player’s Points object.
Set the Value property of the points variable to 0.
local players = game:GetService("Players")
local function onCharacterDied(player)
local points = player.leaderstats.Points
points.Value = 0
end
local function onCharacterAdded(character, player)
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Connect(function()
onCharacterDied(player)
end)
end
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local points = Instance.new("IntValue")
points.Name = "Points"
points.Value = 0
points.Parent = leaderstats
player.CharacterAdded:Connect(function(character)
onCharacterAdded(character, player)
end)
end
players.PlayerAdded:Connect(onPlayerAdded)
Your game is now complete! If you test it out, you’ll see your point score reset to 0 if you die.
[footage of player getting a point, falling into lava, dying, losing points]
Duplicate your platform across your world to create a whole board of disappearing platforms to play on. Try to outlast your friends and see who gets the highest score.
[footage of game being played by multiple players]
Of course, this isn’t a perfect implementation. There are some issues that prevent this from being as playable and customizable as it could be.
If you wanted to change something in the PlatformBehavior script, you’d have to change it dozens of times, making the change in each platform.
Starting on a spawn point in this way also only really works if everyone joins at the same time and agrees to start playing at the same time - a lobby system teleporting you into the game from a separate space when ready would be much better.
Players can’t really interact with each other in this game - it would be much more fun if they could whack each other off platforms, or blow platforms up from a distance.
You’ll learn more about what you need to know to make these kinds of improvements in upcoming courses, as you get closer and closer to making great Roblox games.
# Big long article
In previous courses, you’ve used events to create playable scenes. Most recently, in [Deadly Arena], you’ve made a board of tumbling platforms above a deadly lava floor.
Now it’s time to make something a little more like a real game. You’ll create a of scripted platforms, but this time players should earn points for surviving for longer, and should lose all their points when they die. The platforms should also reset, so that players can play the game more than once.
[footage of players playing on the finished article]
You’ll need to use some new events and features to achieve this.
Setting Up
Before you start coding, you’ll need to set the scene for your game.
Insert a Part for the platform you’ll be scripting - you’ll duplicate this later once you’ve written the code. Make sure it has an appropriate name, like ‘DisappearingPlatform’.
Put a spawn point just above it so that players can jump down to the platform to start the game, and make sure it’s big enough for more than one player to stand on.
[image of part and spawn point in place]
Players need to die when they fall off a platform. You can use the deadly lava floor from [Deadly Arena] in your game to achieve this - or you can just remove the floor entirely and let gravity do the job for you.
How do you award points to players? Even if you made a ‘points’ property for each player, you’d still need a way to display them. Fortunately, Roblox has an easy system for showing points for players called the Leaderboard.
[image of leaderboards with points stat visible]
When you set a player’s points through the Leaderboard, it’ll show up on the right side of the screen in the game. Later, you’ll learn better ways to display all kinds of information through user interfaces, but for now the Leaderboard is the simplest way of making a scoring system in Roblox you can actually see in-game.
Create a Script in the Workspace called SetupLeaderboard. You’ll use this to set up the Leaderboard for each player that joins your game.
Listening for Players
You need an event that will fire when a player joins the game, so that you can set up the points each time and ensure every player has their points displayed. Fortunately, the Players service has an event called PlayerAdded which does exactly that.
A service is an object which exists at the top level of your Roblox game, like Workspace and Lighting. They perform a range of useful functions. The Players service contains a list of all the players in the game, along with other related information. Each player in your game has a corresponding Player object in the Players service.
[image of players in the Players service in the Explorer]
You can access services with the GetService function in the game object. GetService takes a name for a service and returns the service with that name. If it doesn’t exist yet, it’ll create it and then return it.
game is a variable accessible from anywhere. It contains all the things you see in the Explorer window.
Create a variable for the Players service using the GetService function.
Create a function called ‘onPlayerAdded’ with a parameter for the player, so the PlayerAdded event can pass the player to the function when it fires.
Connect the onPlayerAdded function to the PlayerAdded event.





local Players = game:GetService("Players")
local function onPlayerAdded(player)
end
Players.PlayerAdded:Connect(onPlayerAdded)
Just like the Touched event in [Deadly Arena], the PlayerAdded event calls any function connected to it with an argument. In this case, the argument is the player that was added to the game. You’ll need to use the player that was added in your code, so you need to have the parameter to make sure you can access it.
Leaderstats
Time to set up the Leaderboard. To create a points entry in the Leaderboard for a given player, all you need to do is create a new folder in their Player object called ‘leaderstats’, and put the points value in there. Roblox automatically reads and displays any values you put in that folder.
You can create a new folder using Instance.new, which is a special function that can create objects if you give it the name of the type of the object you want. In this case, you want a folder, so you’d write Instance.new(“Folder”).
Create a new folder variable called leaderstats using Instance.new.
Set the Name property of the folder to “leaderstats”.
Put the folder in the Player object by setting the Parent property to player.
local Players = game:GetService("Players")
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
end
Players.PlayerAdded:Connect(onPlayerAdded)
Points Value
The Leaderboard system reads any IntValue objects in the leaderstats folder and will display whatever it finds - so you’ll need to store the points as an IntValue.
An IntValue is a type of object that stores a whole number (an integer - int for short) and a name to associate with it. Numbers which need to be visible and accessible outside of a given script are typically stored this way.
Create a new IntValue variable called ‘points’ using Instance.new.
Set the Name property of points to “Points”.
Set the Value property of points to 0.
Put the points object in the leaderstats folder by setting the Parent property to leaderstats.
local Players = game:GetService("Players")
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local points = Instance.new("IntValue")
points.Name = "Points"
points.Value = 0
points.Parent = leaderstats
end
Players.PlayerAdded:Connect(onPlayerAdded)
Test your game now, and you should see the Leaderboard appear in the top right with the names of your players and a points score next to them.
If you look at the Explorer, you can see that the leaderstats folder is inside the Player object for your player, with the Points object being inside that.
[image of the Explorer showing this]
Scripting the Platform
Next up: making the platforms disappear and award points when you step on them. You should already have inserted a part to act as your platform.
Insert a Script into the platform part.
Create a variable for the platform with script.Parent.
Create a function called ‘onTouched’ with a parameter called ‘otherPart’.
Connect the onTouched function to the platform’s Touched event.
Use a Boolean variable to debounce the onTouched function.
local platform = script.Parent
local isTouched = false
local function onTouched(otherPart)
if not isTouched then
isTouched = true
isTouched = false
end
end
platform.Touched:Connect(onTouched)
The code for the platform behavior will go between the isTouched = true assignment and the isTouched = false assignment.
Making the Platform Disappear
The Transparency and CanCollide properties can be used to make the platform disappear. You can use the code from the [Simple Trap] course to achieve this.
Create a for loop and use the iterator to set the Transparency property of the platform.
Set the CanCollide property of the platform to false, then wait for 20 seconds.
Set the Transparency and CanCollide properties back to their default values.
local platform = script.Parent
local isTouched = false
local function onTouched(otherPart)
if not isTouched then
isTouched = true
for i = 0, 1 do
platform.Transparency = i/10
wait(0.1)
end
platform.CanCollide = false
wait(20)
platform.Transparency = 0
platform.CanCollide = true
isTouched = false
end
end
platform.Touched:Connect(onTouched)
Getting the Player
In order to give a point to the player when they step on the platform, you need to somehow get their Player object out of the otherPart parameter in the onTouched function, as the Player object is where we put the leaderstats folder.
The [Deadly Arena] course covered how every player has a Character model, and a part of this model - e.g. the right leg - is what will actually touch the platform and be passed as an argument to the onTouched function. If a player touches a platform, the parent of the part that touched the platform will therefore be a Character.
So how do you get the Player object from the Character? The Players service has a GetPlayerFromCharacter function that takes a Character as an argument and returns a corresponding Player object. It returns nil if the player doesn’t exist, so it’s important to check the result in case you later cause an error.
Use the GetPlayerFromCharacter function to get the Player object from the parent of the part that touched the platform.
Check that the result exists using an if statement before proceeding.
local platform = script.Parent
local isTouched = false
local Players = game:GetService("Players")
local function onTouched(otherPart)
if not isTouched then
isTouched = true
local character = part.Parent
if character then
local player = Players:GetPlayerFromCharacter(character)
if player then
for i = 0, 1 do
platform.Transparency = i/10
wait(0.1)
end
platform.CanCollide = false
wait(20)
platform.Transparency = 0
platform.CanCollide = true
end
end
isTouched = false
end
end
platform.Touched:Connect(disappear)
Organizing the Script
At this point, the code in the onTouched function is getting unwieldy and difficult to read. Before carrying on, it would be best to split it up and organize it better by creating functions to include the code for each part of the platform’s behavior.
The code for making the platform disappear and reappear is straightforward to move out of the onTouched function, but the code for getting the player object would require access to the otherPart parameter, and would need to provide the result of attempting to get the player object from it. This means we’ll need to create a function with a parameter and a return statement.



v
v

Return Statements
A return statement passes back a value from a function, to be used where the function was called.
It’s how you make your own functions which can do the same sort of thing as e.g. GetPlayerFromCharacter, where the function produces a value you can use.
You just have to write return, followed by the thing you want to pass back.
Move the code for making the platform disappear into its own function.
Move the code for making the platform reappear into its own function.
Move the code for getting the Player object from the otherPart parameter into its own function.
local platform = script.Parent
local isTouched = false
local Players = game:GetService("Players")
local function getPlayerFromPart(part)
local character = part.Parent
if character then
local player = Players:GetPlayerFromCharacter(character)
return player
end
end
local function disappear()
for i = 0, 1 do
platform.Transparency = i/10
wait(0.1)
end
platform.CanCollide = false
end
local function reappear()
platform.Transparency = 0
platform.CanCollide = true
end
local function onTouched(otherPart)
if not isTouched then
isTouched = true
local player = getPlayerFromPart(otherPart)
if player then
disappear()
wait(20)
reappear()
end
isTouched = false
end
end
platform.Touched:Connect(onTouched)
This has all made the script a bit longer, but it’s much easier to read and understand now. It’s important when coding to be efficient, but it’s rarely a good idea to prioritise brevity over clarity.
Awarding a Point
Once you have a Player object in your code, you can add a point to the player’s Points value when they step on the platform. In Lua, you add a number to a variable through assigning it the same way you would assign any other value.
Create a variable called points for the player’s Points object.
Add 1 to the Value property of the points variable.
local platform = script.Parent
local isTouched = false
local Players = game:GetService("Players")
local function getPlayerFromPart(part)
local character = part.Parent
if character then
local player = Players:GetPlayerFromCharacter(character)
return player
end
end
local function disappear()
for i = 0, 1 do
platform.Transparency = i/10
wait(0.1)
end
platform.CanCollide = false
end
local function reappear()
platform.Transparency = 0
platform.CanCollide = true
end
local function onTouched(otherPart)
if not isTouched then
isTouched = true
local player = getPlayerFromPart(otherPart)
if player then
local points = player.leaderstats.Points
points.Value = points.Value + 1
disappear()
wait(20)
reappear()
end
isTouched = false
end
end
platform.Touched:Connect(onTouched)
Test your code now, and you should find that you get a point on the Leaderboard when you step on the platform.
Listening for Characters
Currently, players who die in the game still get to keep all their points, so there’s no incentive to survive for longer. A player’s points should reset to 0 when they die.
The lava floor script from [Deadly Arena] used the Humanoid inside the player’s Character model to kill them, since the Humanoid contains information about a player’s health. Humanoid also has a Died event, which you can use here to find out when a player has died so that you can reset their points.
In order to do this, first you’ll need to get the Character for the player. The Character is only added to the game after the Player object has been loaded. Use the CharacterAdded event in the Player object to listen for when the Character is ready to use.
Create a function called ‘onCharacterAdded’, with two parameters: one for the character, one for the player.
Connect an anonymous function to the CharacterAdded event with a parameter for the character.
In the body of the anonymous function, call the onCharacterAdded function with the character as the first argument and the player as the second.
local players = game:GetService("Players")
local function onCharacterAdded(character, player)
end






local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local points = Instance.new("IntValue")
points.Name = "Points"
points.Value = 0
points.Parent = leaderstats
player.CharacterAdded:Connect(function(character)
onCharacterAdded(character, player)
end)
end
players.PlayerAdded:Connect(onPlayerAdded)
Why the second argument for onCharacterAdded, and why the strange function for the CharacterAdded event?
You need to have the Player object later in your code, because you’ll need to get the Points value from the player’s leaderstats folder. But the CharacterAdded event doesn’t provide the Player object to the function that connects to it - it only provides the Character.
Ideally, you’d want the CharacterAdded event to call a function which then calls the onCharacterAdded function with an extra player argument for the Player object. Otherwise, if you connected the onCharacterAdded function directly to the event, you wouldn’t be able to pass it the Player object. Here, an anonymous function is used to create this ‘wrapper’ function.
Anonymous Functions
This is a function with no name, which can be treated as a value.
It’s used here to efficiently ‘wrap’ a call to the function you actually want to run - i.e. onCharacterAdded - so that we can call it with a bonus argument for the player.
A wrapper function like this doesn’t need a name, so being able to put it directly into the parentheses for the event connection saves space and keeps things simple.
Listening for the Humanoid
The Died event you’re looking for is in the Humanoid, inside the Character object. You need to wait for the Humanoid object to be loaded in first - the Humanoid won’t necessarily be there just because the Character model is present. If you try to connect to the event before the Humanoid has loaded, you’ll cause an error.
Every object in Roblox has a WaitForChild function, which looks for an object with a given name and stops the code until it finds it. It takes the name of the object you’re looking for as a String. You can use it here to get the Humanoid safely before connecting to the Died event.
It’s best to connect to the Died event using an anonymous function as a wrapper, so that you can pass the player through and use it later to reset the points.
Create a variable for the Humanoid, and assign to it the result of calling WaitForChild on the character with the argument ‘Humanoid’.
Create a function called ‘onCharacterDied’, with a parameter for the player.
Connect an anonymous function to the Died event of the Humanoid variable.
In the body of the anonymous function, call the onCharacterDied function with the player as an argument.
local players = game:GetService("Players")
local function onCharacterDied(player)
end
local function onCharacterAdded(character, player)
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Connect(function()
onCharacterDied(player)
end)
end
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local points = Instance.new("IntValue")
points.Name = "Points"
points.Value = 0
points.Parent = leaderstats
player.CharacterAdded:Connect(function(character)
onCharacterAdded(character, player)
end)
end
players.PlayerAdded:Connect(onPlayerAdded)
Resetting the Points
Finally, you can reset the player’s points in the onCharacterDied function using the player parameter.
Create a variable called ‘points’ for the player’s Points object.
Set the Value property of the points variable to 0.
local players = game:GetService("Players")
local function onCharacterDied(player)
local points = player.leaderstats.Points
points.Value = 0
end
local function onCharacterAdded(character, player)
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Connect(function()
onCharacterDied(player)
end)
end
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local points = Instance.new("IntValue")
points.Name = "Points"
points.Value = 0
points.Parent = leaderstats
player.CharacterAdded:Connect(function(character)
onCharacterAdded(character, player)
end)
end
players.PlayerAdded:Connect(onPlayerAdded)
Your game is now complete! If you test it out, you’ll see your point score reset to 0 if you die.
[footage of player getting a point, falling into lava, dying, losing points]
Duplicate your platform across your world to create a whole board of disappearing platforms to play on. Try to outlast your friends and see who gets the highest score.
[footage of game being played by multiple players]
Of course, this isn’t a perfect implementation. There are some issues that prevent this from being as playable and customizable as it could be.
If you wanted to change something in the PlatformBehavior script, you’d have to change it dozens of times, making the change in each platform.
Starting on a spawn point in this way also only really works if everyone joins at the same time and agrees to start playing at the same time - a lobby system teleporting you into the game from a separate space when ready would be much better.
Players can’t really interact with each other in this game - it would be much more fun if they could whack each other off platforms, or blow platforms up from a distance.
You’ll learn more about what you need to know to make these kinds of improvements in upcoming courses, as you get closer and closer to making great Roblox games.
# Big long article
In previous courses, you’ve used events to create playable scenes. Most recently, in [Deadly Arena], you’ve made a board of tumbling platforms above a deadly lava floor.
Now it’s time to make something a little more like a real game. You’ll create a of scripted platforms, but this time players should earn points for surviving for longer, and should lose all their points when they die. The platforms should also reset, so that players can play the game more than once.
[footage of players playing on the finished article]
You’ll need to use some new events and features to achieve this.
Setting Up
Before you start coding, you’ll need to set the scene for your game.
Insert a Part for the platform you’ll be scripting - you’ll duplicate this later once you’ve written the code. Make sure it has an appropriate name, like ‘DisappearingPlatform’.
Put a spawn point just above it so that players can jump down to the platform to start the game, and make sure it’s big enough for more than one player to stand on.
[image of part and spawn point in place]
Players need to die when they fall off a platform. You can use the deadly lava floor from [Deadly Arena] in your game to achieve this - or you can just remove the floor entirely and let gravity do the job for you.
How do you award points to players? Even if you made a ‘points’ property for each player, you’d still need a way to display them. Fortunately, Roblox has an easy system for showing points for players called the Leaderboard.
[image of leaderboards with points stat visible]
When you set a player’s points through the Leaderboard, it’ll show up on the right side of the screen in the game. Later, you’ll learn better ways to display all kinds of information through user interfaces, but for now the Leaderboard is the simplest way of making a scoring system in Roblox you can actually see in-game.
Create a Script in the Workspace called SetupLeaderboard. You’ll use this to set up the Leaderboard for each player that joins your game.
Listening for Players
You need an event that will fire when a player joins the game, so that you can set up the points each time and ensure every player has their points displayed. Fortunately, the Players service has an event called PlayerAdded which does exactly that.
A service is an object which exists at the top level of your Roblox game, like Workspace and Lighting. They perform a range of useful functions. The Players service contains a list of all the players in the game, along with other related information. Each player in your game has a corresponding Player object in the Players service.
[image of players in the Players service in the Explorer]
You can access services with the GetService function in the game object. GetService takes a name for a service and returns the service with that name. If it doesn’t exist yet, it’ll create it and then return it.
game is a variable accessible from anywhere. It contains all the things you see in the Explorer window.
Create a variable for the Players service using the GetService function.
Create a function called ‘onPlayerAdded’ with a parameter for the player, so the PlayerAdded event can pass the player to the function when it fires.
Connect the onPlayerAdded function to the PlayerAdded event.
local Players = game:GetService("Players")
local function onPlayerAdded(player)
end
Players.PlayerAdded:Connect(onPlayerAdded)
Just like the Touched event in [Deadly Arena], the PlayerAdded event calls any function connected to it with an argument. In this case, the argument is the player that was added to the game. You’ll need to use the player that was added in your code, so you need to have the parameter to make sure you can access it.
Leaderstats
Time to set up the Leaderboard. To create a points entry in the Leaderboard for a given player, all you need to do is create a new folder in their Player object called ‘leaderstats’, and put the points value in there. Roblox automatically reads and displays any values you put in that folder.
You can create a new folder using Instance.new, which is a special function that can create objects if you give it the name of the type of the object you want. In this case, you want a folder, so you’d write Instance.new(“Folder”).
Create a new folder variable called leaderstats using Instance.new.
Set the Name property of the folder to “leaderstats”.
Put the folder in the Player object by setting the Parent property to player.
local Players = game:GetService("Players")
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
end
Players.PlayerAdded:Connect(onPlayerAdded)
Points Value
The Leaderboard system reads any IntValue objects in the leaderstats folder and will display whatever it finds - so you’ll need to store the points as an IntValue.
An IntValue is a type of object that stores a whole number (an integer - int for short) and a name to associate with it. Numbers which need to be visible and accessible outside of a given script are typically stored this way.
Create a new IntValue variable called ‘points’ using Instance.new.
Set the Name property of points to “Points”.
Set the Value property of points to 0.
Put the points object in the leaderstats folder by setting the Parent property to leaderstats.
local Players = game:GetService("Players")
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local points = Instance.new("IntValue")
points.Name = "Points"
points.Value = 0
points.Parent = leaderstats
end
Players.PlayerAdded:Connect(onPlayerAdded)
Test your game now, and you should see the Leaderboard appear in the top right with the names of your players and a points score next to them.
If you look at the Explorer, you can see that the leaderstats folder is inside the Player object for your player, with the Points object being inside that.
[image of the Explorer showing this]
Scripting the Platform
Next up: making the platforms disappear and award points when you step on them. You should already have inserted a part to act as your platform.
Insert a Script into the platform part.
Create a variable for the platform with script.Parent.
Create a function called ‘onTouched’ with a parameter called ‘otherPart’.
Connect the onTouched function to the platform’s Touched event.
Use a Boolean variable to debounce the onTouched function.
local platform = script.Parent
local isTouched = false
local function onTouched(otherPart)
if not isTouched then
isTouched = true
isTouched = false
end
end
platform.Touched:Connect(onTouched)
The code for the platform behavior will go between the isTouched = true assignment and the isTouched = false assignment.
Making the Platform Disappear
The Transparency and CanCollide properties can be used to make the platform disappear. You can use the code from the [Simple Trap] course to achieve this.
Create a for loop and use the iterator to set the Transparency property of the platform.
Set the CanCollide property of the platform to false, then wait for 20 seconds.
Set the Transparency and CanCollide properties back to their default values.
local platform = script.Parent
local isTouched = false
local function onTouched(otherPart)
if not isTouched then
isTouched = true
for i = 0, 1 do
platform.Transparency = i/10
wait(0.1)
end
platform.CanCollide = false
wait(20)
platform.Transparency = 0
platform.CanCollide = true
isTouched = false
end
end
platform.Touched:Connect(onTouched)
Getting the Player
In order to give a point to the player when they step on the platform, you need to somehow get their Player object out of the otherPart parameter in the onTouched function, as the Player object is where we put the leaderstats folder.
The [Deadly Arena] course covered how every player has a Character model, and a part of this model - e.g. the right leg - is what will actually touch the platform and be passed as an argument to the onTouched function. If a player touches a platform, the parent of the part that touched the platform will therefore be a Character.
So how do you get the Player object from the Character? The Players service has a GetPlayerFromCharacter function that takes a Character as an argument and returns a corresponding Player object. It returns nil if the player doesn’t exist, so it’s important to check the result in case you later cause an error.
Use the GetPlayerFromCharacter function to get the Player object from the parent of the part that touched the platform.
Check that the result exists using an if statement before proceeding.
local platform = script.Parent
local isTouched = false
local Players = game:GetService("Players")
local function onTouched(otherPart)
if not isTouched then
isTouched = true
local character = part.Parent
if character then
local player = Players:GetPlayerFromCharacter(character)
if player then
for i = 0, 1 do
platform.Transparency = i/10
wait(0.1)
end
platform.CanCollide = false
wait(20)
platform.Transparency = 0
platform.CanCollide = true
end
end
isTouched = false
end
end
platform.Touched:Connect(disappear)
Organizing the Script
At this point, the code in the onTouched function is getting unwieldy and difficult to read. Before carrying on, it would be best to split it up and organize it better by creating functions to include the code for each part of the platform’s behavior.
The code for making the platform disappear and reappear is straightforward to move out of the onTouched function, but the code for getting the player object would require access to the otherPart parameter, and would need to provide the result of attempting to get the player object from it. This means we’ll need to create a function with a parameter and a return statement.
Return Statements
A return statement passes back a value from a function, to be used where the function was called.
It’s how you make your own functions which can do the same sort of thing as e.g. GetPlayerFromCharacter, where the function produces a value you can use.
You just have to write return, followed by the thing you want to pass back.
Move the code for making the platform disappear into its own function.
Move the code for making the platform reappear into its own function.
Move the code for getting the Player object from the otherPart parameter into its own function.
local platform = script.Parent
local isTouched = false
local Players = game:GetService("Players")
local function getPlayerFromPart(part)
local character = part.Parent
if character then
local player = Players:GetPlayerFromCharacter(character)
return player
end
end
local function disappear()
for i = 0, 1 do
platform.Transparency = i/10
wait(0.1)
end
platform.CanCollide = false
end
local function reappear()
platform.Transparency = 0
platform.CanCollide = true
end
local function onTouched(otherPart)
if not isTouched then
isTouched = true
local player = getPlayerFromPart(otherPart)
if player then
disappear()
wait(20)
reappear()
end
isTouched = false
end
end
platform.Touched:Connect(onTouched)
This has all made the script a bit longer, but it’s much easier to read and understand now. It’s important when coding to be efficient, but it’s rarely a good idea to prioritise brevity over clarity.
Awarding a Point
Once you have a Player object in your code, you can add a point to the player’s Points value when they step on the platform. In Lua, you add a number to a variable through assigning it the same way you would assign any other value.
Create a variable called points for the player’s Points object.
Add 1 to the Value property of the points variable.
local platform = script.Parent
local isTouched = false
local Players = game:GetService("Players")
local function getPlayerFromPart(part)
local character = part.Parent
if character then
local player = Players:GetPlayerFromCharacter(character)
return player
end
end
local function disappear()
for i = 0, 1 do
platform.Transparency = i/10
wait(0.1)
end
platform.CanCollide = false
end
local function reappear()
platform.Transparency = 0
platform.CanCollide = true
end
local function onTouched(otherPart)
if not isTouched then
isTouched = true
local player = getPlayerFromPart(otherPart)
if player then
local points = player.leaderstats.Points
points.Value = points.Value + 1
disappear()
wait(20)
reappear()
end
isTouched = false
end
end
platform.Touched:Connect(onTouched)
Test your code now, and you should find that you get a point on the Leaderboard when you step on the platform.
Listening for Characters
Currently, players who die in the game still get to keep all their points, so there’s no incentive to survive for longer. A player’s points should reset to 0 when they die.
The lava floor script from [Deadly Arena] used the Humanoid inside the player’s Character model to kill them, since the Humanoid contains information about a player’s health. Humanoid also has a Died event, which you can use here to find out when a player has died so that you can reset their points.
In order to do this, first you’ll need to get the Character for the player. The Character is only added to the game after the Player object has been loaded. Use the CharacterAdded event in the Player object to listen for when the Character is ready to use.
Create a function called ‘onCharacterAdded’, with two parameters: one for the character, one for the player.
Connect an anonymous function to the CharacterAdded event with a parameter for the character.
In the body of the anonymous function, call the onCharacterAdded function with the character as the first argument and the player as the second.
local players = game:GetService("Players")
local function onCharacterAdded(character, player)
end
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local points = Instance.new("IntValue")
points.Name = "Points"
points.Value = 0
points.Parent = leaderstats
player.CharacterAdded:Connect(function(character)
onCharacterAdded(character, player)
end)
end
players.PlayerAdded:Connect(onPlayerAdded)
Why the second argument for onCharacterAdded, and why the strange function for the CharacterAdded event?
You need to have the Player object later in your code, because you’ll need to get the Points value from the player’s leaderstats folder. But the CharacterAdded event doesn’t provide the Player object to the function that connects to it - it only provides the Character.
Ideally, you’d want the CharacterAdded event to call a function which then calls the onCharacterAdded function with an extra player argument for the Player object. Otherwise, if you connected the onCharacterAdded function directly to the event, you wouldn’t be able to pass it the Player object. Here, an anonymous function is used to create this ‘wrapper’ function.
Anonymous Functions
This is a function with no name, which can be treated as a value.
It’s used here to efficiently ‘wrap’ a call to the function you actually want to run - i.e. onCharacterAdded - so that we can call it with a bonus argument for the player.
A wrapper function like this doesn’t need a name, so being able to put it directly into the parentheses for the event connection saves space and keeps things simple.
Listening for the Humanoid
The Died event you’re looking for is in the Humanoid, inside the Character object. You need to wait for the Humanoid object to be loaded in first - the Humanoid won’t necessarily be there just because the Character model is present. If you try to connect to the event before the Humanoid has loaded, you’ll cause an error.
Every object in Roblox has a WaitForChild function, which looks for an object with a given name and stops the code until it finds it. It takes the name of the object you’re looking for as a String. You can use it here to get the Humanoid safely before connecting to the Died event.
It’s best to connect to the Died event using an anonymous function as a wrapper, so that you can pass the player through and use it later to reset the points.
Create a variable for the Humanoid, and assign to it the result of calling WaitForChild on the character with the argument ‘Humanoid’.
Create a function called ‘onCharacterDied’, with a parameter for the player.
Connect an anonymous function to the Died event of the Humanoid variable.
In the body of the anonymous function, call the onCharacterDied function with the player as an argument.
local players = game:GetService("Players")
local function onCharacterDied(player)
end
local function onCharacterAdded(character, player)
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Connect(function()
onCharacterDied(player)
end)
end
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local points = Instance.new("IntValue")
points.Name = "Points"
points.Value = 0
points.Parent = leaderstats
player.CharacterAdded:Connect(function(character)
onCharacterAdded(character, player)
end)
end
players.PlayerAdded:Connect(onPlayerAdded)
Resetting the Points
Finally, you can reset the player’s points in the onCharacterDied function using the player parameter.
Create a variable called ‘points’ for the player’s Points object.
Set the Value property of the points variable to 0.
local players = game:GetService("Players")
local function onCharacterDied(player)
local points = player.leaderstats.Points
points.Value = 0
end
local function onCharacterAdded(character, player)
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Connect(function()
onCharacterDied(player)
end)
end
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local points = Instance.new("IntValue")
points.Name = "Points"
points.Value = 0
points.Parent = leaderstats
player.CharacterAdded:Connect(function(character)
onCharacterAdded(character, player)
end)
end
players.PlayerAdded:Connect(onPlayerAdded)
Your game is now complete! If you test it out, you’ll see your point score reset to 0 if you die.
[footage of player getting a point, falling into lava, dying, losing points]
Duplicate your platform across your world to create a whole board of disappearing platforms to play on. Try to outlast your friends and see who gets the highest score.
[footage of game being played by multiple players]
Of course, this isn’t a perfect implementation. There are some issues that prevent this from being as playable and customizable as it could be.
If you wanted to change something in the PlatformBehavior script, you’d have to change it dozens of times, making the change in each platform.
Starting on a spawn point in this way also only really works if everyone joins at the same time and agrees to start playing at the same time - a lobby system teleporting you into the game from a separate space when ready would be much better.
Players can’t really interact with each other in this game - it would be much more fun if they could whack each other off platforms, or blow platforms up from a distance.
You’ll learn more about what you need to know to make these kinds of improvements in upcoming courses, as you get closer and closer to making great Roblox games.
# Big long article
In previous courses, you’ve used events to create playable scenes. Most recently, in [Deadly Arena], you’ve made a board of tumbling platforms above a deadly lava floor.
Now it’s time to make something a little more like a real game. You’ll create a of scripted platforms, but this time players should earn points for surviving for longer, and should lose all their points when they die. The platforms should also reset, so that players can play the game more than once.
[footage of players playing on the finished article]
You’ll need to use some new events and features to achieve this.
Setting Up
Before you start coding, you’ll need to set the scene for your game.
Insert a Part for the platform you’ll be scripting - you’ll duplicate this later once you’ve written the code. Make sure it has an appropriate name, like ‘DisappearingPlatform’.
Put a spawn point just above it so that players can jump down to the platform to start the game, and make sure it’s big enough for more than one player to stand on.
[image of part and spawn point in place]
Players need to die when they fall off a platform. You can use the deadly lava floor from [Deadly Arena] in your game to achieve this - or you can just remove the floor entirely and let gravity do the job for you.
How do you award points to players? Even if you made a ‘points’ property for each player, you’d still need a way to display them. Fortunately, Roblox has an easy system for showing points for players called the Leaderboard.
[image of leaderboards with points stat visible]
When you set a player’s points through the Leaderboard, it’ll show up on the right side of the screen in the game. Later, you’ll learn better ways to display all kinds of information through user interfaces, but for now the Leaderboard is the simplest way of making a scoring system in Roblox you can actually see in-game.
Create a Script in the Workspace called SetupLeaderboard. You’ll use this to set up the Leaderboard for each player that joins your game.
Listening for Players
You need an event that will fire when a player joins the game, so that you can set up the points each time and ensure every player has their points displayed. Fortunately, the Players service has an event called PlayerAdded which does exactly that.
A service is an object which exists at the top level of your Roblox game, like Workspace and Lighting. They perform a range of useful functions. The Players service contains a list of all the players in the game, along with other related information. Each player in your game has a corresponding Player object in the Players service.
[image of players in the Players service in the Explorer]
You can access services with the GetService function in the game object. GetService takes a name for a service and returns the service with that name. If it doesn’t exist yet, it’ll create it and then return it.
game is a variable accessible from anywhere. It contains all the things you see in the Explorer window.
Create a variable for the Players service using the GetService function.
Create a function called ‘onPlayerAdded’ with a parameter for the player, so the PlayerAdded event can pass the player to the function when it fires.
Connect the onPlayerAdded function to the PlayerAdded event.
local Players = game:GetService("Players")
local function onPlayerAdded(player)
end
Players.PlayerAdded:Connect(onPlayerAdded)
Just like the Touched event in [Deadly Arena], the PlayerAdded event calls any function connected to it with an argument. In this case, the argument is the player that was added to the game. You’ll need to use the player that was added in your code, so you need to have the parameter to make sure you can access it.
Leaderstats
Time to set up the Leaderboard. To create a points entry in the Leaderboard for a given player, all you need to do is create a new folder in their Player object called ‘leaderstats’, and put the points value in there. Roblox automatically reads and displays any values you put in that folder.
You can create a new folder using Instance.new, which is a special function that can create objects if you give it the name of the type of the object you want. In this case, you want a folder, so you’d write Instance.new(“Folder”).
Create a new folder variable called leaderstats using Instance.new.
Set the Name property of the folder to “leaderstats”.
Put the folder in the Player object by setting the Parent property to player.
local Players = game:GetService("Players")
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
end
Players.PlayerAdded:Connect(onPlayerAdded)
Points Value
The Leaderboard system reads any IntValue objects in the leaderstats folder and will display whatever it finds - so you’ll need to store the points as an IntValue.
An IntValue is a type of object that stores a whole number (an integer - int for short) and a name to associate with it. Numbers which need to be visible and accessible outside of a given script are typically stored this way.
Create a new IntValue variable called ‘points’ using Instance.new.
Set the Name property of points to “Points”.
Set the Value property of points to 0.
Put the points object in the leaderstats folder by setting the Parent property to leaderstats.
local Players = game:GetService("Players")
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local points = Instance.new("IntValue")
points.Name = "Points"
points.Value = 0
points.Parent = leaderstats
end
Players.PlayerAdded:Connect(onPlayerAdded)
Test your game now, and you should see the Leaderboard appear in the top right with the names of your players and a points score next to them.
If you look at the Explorer, you can see that the leaderstats folder is inside the Player object for your player, with the Points object being inside that.
[image of the Explorer showing this]
Scripting the Platform
Next up: making the platforms disappear and award points when you step on them. You should already have inserted a part to act as your platform.
Insert a Script into the platform part.
Create a variable for the platform with script.Parent.
Create a function called ‘onTouched’ with a parameter called ‘otherPart’.
Connect the onTouched function to the platform’s Touched event.
Use a Boolean variable to debounce the onTouched function.
local platform = script.Parent
local isTouched = false
local function onTouched(otherPart)
if not isTouched then
isTouched = true
isTouched = false
end
end
platform.Touched:Connect(onTouched)
The code for the platform behavior will go between the isTouched = true assignment and the isTouched = false assignment.
Making the Platform Disappear
The Transparency and CanCollide properties can be used to make the platform disappear. You can use the code from the [Simple Trap] course to achieve this.
Create a for loop and use the iterator to set the Transparency property of the platform.
Set the CanCollide property of the platform to false, then wait for 20 seconds.
Set the Transparency and CanCollide properties back to their default values.
local platform = script.Parent
local isTouched = false
local function onTouched(otherPart)
if not isTouched then
isTouched = true
for i = 0, 1 do
platform.Transparency = i/10
wait(0.1)
end
platform.CanCollide = false
wait(20)
platform.Transparency = 0
platform.CanCollide = true
isTouched = false
end
end
platform.Touched:Connect(onTouched)
Getting the Player
In order to give a point to the player when they step on the platform, you need to somehow get their Player object out of the otherPart parameter in the onTouched function, as the Player object is where we put the leaderstats folder.
The [Deadly Arena] course covered how every player has a Character model, and a part of this model - e.g. the right leg - is what will actually touch the platform and be passed as an argument to the onTouched function. If a player touches a platform, the parent of the part that touched the platform will therefore be a Character.
So how do you get the Player object from the Character? The Players service has a GetPlayerFromCharacter function that takes a Character as an argument and returns a corresponding Player object. It returns nil if the player doesn’t exist, so it’s important to check the result in case you later cause an error.
Use the GetPlayerFromCharacter function to get the Player object from the parent of the part that touched the platform.
Check that the result exists using an if statement before proceeding.
local platform = script.Parent
local isTouched = false
local Players = game:GetService("Players")
local function onTouched(otherPart)
if not isTouched then
isTouched = true
local character = part.Parent
if character then
local player = Players:GetPlayerFromCharacter(character)
if player then
for i = 0, 1 do
platform.Transparency = i/10
wait(0.1)
end
platform.CanCollide = false
wait(20)
platform.Transparency = 0
platform.CanCollide = true
end
end
isTouched = false
end
end
platform.Touched:Connect(disappear)
Organizing the Script
At this point, the code in the onTouched function is getting unwieldy and difficult to read. Before carrying on, it would be best to split it up and organize it better by creating functions to include the code for each part of the platform’s behavior.
The code for making the platform disappear and reappear is straightforward to move out of the onTouched function, but the code for getting the player object would require access to the otherPart parameter, and would need to provide the result of attempting to get the player object from it. This means we’ll need to create a function with a parameter and a return statement.
Return Statements
A return statement passes back a value from a function, to be used where the function was called.
It’s how you make your own functions which can do the same sort of thing as e.g. GetPlayerFromCharacter, where the function produces a value you can use.
You just have to write return, followed by the thing you want to pass back.
Move the code for making the platform disappear into its own function.
Move the code for making the platform reappear into its own function.
Move the code for getting the Player object from the otherPart parameter into its own function.
local platform = script.Parent
local isTouched = false
local Players = game:GetService("Players")
local function getPlayerFromPart(part)
local character = part.Parent
if character then
local player = Players:GetPlayerFromCharacter(character)
return player
end
end
local function disappear()
for i = 0, 1 do
platform.Transparency = i/10
wait(0.1)
end
platform.CanCollide = false
end
local function reappear()
platform.Transparency = 0
platform.CanCollide = true
end
local function onTouched(otherPart)
if not isTouched then
isTouched = true
local player = getPlayerFromPart(otherPart)
if player then
disappear()
wait(20)
reappear()
end
isTouched = false
end
end
platform.Touched:Connect(onTouched)
This has all made the script a bit longer, but it’s much easier to read and understand now. It’s important when coding to be efficient, but it’s rarely a good idea to prioritise brevity over clarity.
Awarding a Point
Once you have a Player object in your code, you can add a point to the player’s Points value when they step on the platform. In Lua, you add a number to a variable through assigning it the same way you would assign any other value.
Create a variable called points for the player’s Points object.
Add 1 to the Value property of the points variable.
local platform = script.Parent
local isTouched = false
local Players = game:GetService("Players")
local function getPlayerFromPart(part)
local character = part.Parent
if character then
local player = Players:GetPlayerFromCharacter(character)
return player
end
end
local function disappear()
for i = 0, 1 do
platform.Transparency = i/10
wait(0.1)
end
platform.CanCollide = false
end
local function reappear()
platform.Transparency = 0
platform.CanCollide = true
end
local function onTouched(otherPart)
if not isTouched then
isTouched = true
local player = getPlayerFromPart(otherPart)
if player then
local points = player.leaderstats.Points
points.Value = points.Value + 1
disappear()
wait(20)
reappear()
end
isTouched = false
end
end
platform.Touched:Connect(onTouched)
Test your code now, and you should find that you get a point on the Leaderboard when you step on the platform.
Listening for Characters
Currently, players who die in the game still get to keep all their points, so there’s no incentive to survive for longer. A player’s points should reset to 0 when they die.
The lava floor script from [Deadly Arena] used the Humanoid inside the player’s Character model to kill them, since the Humanoid contains information about a player’s health. Humanoid also has a Died event, which you can use here to find out when a player has died so that you can reset their points.
In order to do this, first you’ll need to get the Character for the player. The Character is only added to the game after the Player object has been loaded. Use the CharacterAdded event in the Player object to listen for when the Character is ready to use.
Create a function called ‘onCharacterAdded’, with two parameters: one for the character, one for the player.
Connect an anonymous function to the CharacterAdded event with a parameter for the character.
In the body of the anonymous function, call the onCharacterAdded function with the character as the first argument and the player as the second.
local players = game:GetService("Players")
local function onCharacterAdded(character, player)
end
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local points = Instance.new("IntValue")
points.Name = "Points"
points.Value = 0
points.Parent = leaderstats
player.CharacterAdded:Connect(function(character)
onCharacterAdded(character, player)
end)
end
players.PlayerAdded:Connect(onPlayerAdded)
Why the second argument for onCharacterAdded, and why the strange function for the CharacterAdded event?
You need to have the Player object later in your code, because you’ll need to get the Points value from the player’s leaderstats folder. But the CharacterAdded event doesn’t provide the Player object to the function that connects to it - it only provides the Character.
Ideally, you’d want the CharacterAdded event to call a function which then calls the onCharacterAdded function with an extra player argument for the Player object. Otherwise, if you connected the onCharacterAdded function directly to the event, you wouldn’t be able to pass it the Player object. Here, an anonymous function is used to create this ‘wrapper’ function.
Anonymous Functions
This is a function with no name, which can be treated as a value.
It’s used here to efficiently ‘wrap’ a call to the function you actually want to run - i.e. onCharacterAdded - so that we can call it with a bonus argument for the player.
A wrapper function like this doesn’t need a name, so being able to put it directly into the parentheses for the event connection saves space and keeps things simple.
Listening for the Humanoid
The Died event you’re looking for is in the Humanoid, inside the Character object. You need to wait for the Humanoid object to be loaded in first - the Humanoid won’t necessarily be there just because the Character model is present. If you try to connect to the event before the Humanoid has loaded, you’ll cause an error.
Every object in Roblox has a WaitForChild function, which looks for an object with a given name and stops the code until it finds it. It takes the name of the object you’re looking for as a String. You can use it here to get the Humanoid safely before connecting to the Died event.
It’s best to connect to the Died event using an anonymous function as a wrapper, so that you can pass the player through and use it later to reset the points.
Create a variable for the Humanoid, and assign to it the result of calling WaitForChild on the character with the argument ‘Humanoid’.
Create a function called ‘onCharacterDied’, with a parameter for the player.
Connect an anonymous function to the Died event of the Humanoid variable.
In the body of the anonymous function, call the onCharacterDied function with the player as an argument.
local players = game:GetService("Players")
local function onCharacterDied(player)
end
local function onCharacterAdded(character, player)
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Connect(function()
onCharacterDied(player)
end)
end
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local points = Instance.new("IntValue")
points.Name = "Points"
points.Value = 0
points.Parent = leaderstats
player.CharacterAdded:Connect(function(character)
onCharacterAdded(character, player)
end)
end
players.PlayerAdded:Connect(onPlayerAdded)
Resetting the Points
Finally, you can reset the player’s points in the onCharacterDied function using the player parameter.
Create a variable called ‘points’ for the player’s Points object.
Set the Value property of the points variable to 0.
local players = game:GetService("Players")
local function onCharacterDied(player)
local points = player.leaderstats.Points
points.Value = 0
end
local function onCharacterAdded(character, player)
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Connect(function()
onCharacterDied(player)
end)
end
local function onPlayerAdded(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local points = Instance.new("IntValue")
points.Name = "Points"
points.Value = 0
points.Parent = leaderstats
player.CharacterAdded:Connect(function(character)
onCharacterAdded(character, player)
end)
end
players.PlayerAdded:Connect(onPlayerAdded)













































Your game is now complete! If you test it out, you’ll see your point score reset to 0 if you die.
[footage of player getting a point, falling into lava, dying, losing points]
Duplicate your platform across your world to create a whole board of disappearing platforms to play on. Try to outlast your friends and see who gets the highest score.
[footage of game being played by multiple players]
Of course, this isn’t a perfect implementation. There are some issues that prevent this from being as playable and customizable as it could be.
If you wanted to change something in the PlatformBehavior script, you’d have to change it dozens of times, making the change in each platform.
Starting on a spawn point in this way also only really works if everyone joins at the same time and agrees to start playing at the same time - a lobby system teleporting you into the game from a separate space when ready would be much better.
Players can’t really interact with each other in this game - it would be much more fun if they could whack each other off platforms, or blow platforms up from a distance.
You’ll learn more about what you need to know to make these kinds of improvements in upcoming courses, as yoWEFOSIEWCLOSER TO CHSAu get closer and closer to making great Roblox games. Hello this is a test to see how it copes. It seems to cope absolutely fine theid


































How is it doing now? Is it updating properly?