Things you should know before reading this tutorial
- Basic events
- Basics of functions
- Basics of CFrame
- Creating leaderstats
Not into words? No problem!
Video Tutorial Here
The checkpoint system
Checkpoints are one of the most important parts of an obby, its a way for your players to know where they are, a way for better players to flex on noobs and it saves the progress of the player.
So how do you make this?
First create the model for your checkpoint, I’m going to stick with a neon white part. You don’t really need something super fancy, nobody really cares what the checkpoints in your game look like.
Here are the properties of my checkpoint if you really care:
- Size: 5,1,5
- Material: Neon
- BrickColor: Institutional white
- Anchored: true
Hopefully you remembered to anchor your checkpoint…
Now that you’ve made your checkpoints, we’re going to need a folder to store all these checkpoints in. Start by creating a folder inside of the workspace, just for naming sake, you should name it something along the lines of “Checkpoints”. Next parent the checkpoint you made to that folder. You should name all checkpoints you make relative to the checkpoint’s corresponding stage. Example:
Time to get scripting
Let’s begin with creating an auto saving data store… (I’ll be sticking with something simple and somewhat unreliable, if you’d like something better I suggest Data Store 2 by @Kampfkarren → How to use DataStore2 - Data Store caching and data loss prevention - #476 by Tybearic)
local StageData = game:GetService("DataStoreService"):GetDataStore("StageData")
--[[
* The DataStoreService is responsible for storing data (it's in the name)
Creating a new data store is simple
* The :GetDataStore(data store: string) function simply finds a data store by the name given in the parameters
or creates a new data store by that name if one doesn't already exist
* The data from these data stores is quite easy to retrieve...
Each data store comes with some more functions
* DataStore:GetAsync(key: any)
In this game we'd do something like this
StageData:GetAsync(player.UserId)
The player's userid will be the key for retrieving their saved data in this case
* DataStore:SetAsync(key: any, updated data: any)
The SetAsync function sets the data for the data store
]]
local Checkpoints = workspace:WaitForChild("Checkpoints"):GetChildren()
-- A table of all checkpoints we created earlier
-- :WaitForChild("Checkpoints") waits until there's an object called "Checkpoints" in the workspace if there isn't one already
-- We do this because sometimes this script can load in before the checkpoints folder
-- :GetChildren() finds all parts inside of an object
function GoToCheckpoint(character, stage)
local rootPart = character:WaitForChild("HumanoidRootPart")
repeat wait(0.00) until rootPart
-- The HumanoidRootPart of the character is basically where the character is (it has other uses as well)
-- If we change the cframe/position of the root part then the character comes with it
for i, checkpoint in pairs(Checkpoints) do
-- Loops through all the checkpoints so we can find the right one
print("Checkpoint" .. tostring(stage))
if ("Checkpoint" .. tostring(stage)) == checkpoint.Name then
print("Checkpoint found")
rootPart.CFrame = checkpoint.CFrame * CFrame.new(0,1,0)
-- Change the CFrame of the root part to the player's stage (it's kinda like position)
-- We're multiplying by CFrame.new(0,1,0) so the player doesn't spawn inside of the checkpoint
break
-- Stop looping since we found the checkpoint
end
end
end
game:GetService("Players").PlayerAdded:Connect(function(player)
-- The function we're connecting to this event will be called everytime a player joins the game
local leaderstats = Instance.new("Folder", player)
leaderstats.Name = "leaderstats"
local stage = Instance.new("IntValue", leaderstats)
stage.Name = "Stage"
stage.Value = StageData:GetAsync(player.UserId) or 1
-- Retrieve the player's data, but if there is none, start the player on stage 1
player.CharacterAdded:Connect(function(character)
-- The function we're connecting to this event will be called everytime the player's character spawns
GoToCheckpoint(character, stage.Value)
end)
end)
for i, checkpoint in pairs(Checkpoints) do
checkpoint.Touched:Connect(function(touch)
-- Touched is an event that is fired when the object is touched
local hum = touch.Parent:FindFirstChild("Humanoid")
-- If a part in a model touches the part, touch = that part not the model
if hum and hum.Health > 0 then
-- The thing that touched the checkpoint is alive
local player = game:GetService("Players"):GetPlayerFromCharacter(touch.Parent)
-- This allows us to find a player with their character (it's very useful)
if player then
-- Whatever touched the checkpoint is a player
local leaderstats = player:WaitForChild("leaderstats")
local stage = leaderstats:WaitForChild("Stage")
-- Find the stage leader stat
if (tonumber(checkpoint.Name:match("%d+"))-stage.Value) == 1 then
-- match() finds certain parts in a string
-- So when we do match("%d"), we're finding the numbers in a string
-- This is the player's next checkpoint
-- This makes it so player's can't skip checkpoints
-- or lose progress if they accidently go backwards
stage.Value = stage.Value + 1
end
end
end
end)
end
game:GetService("Players").PlayerRemoving:Connect(function(player)
StageData:SetAsync(player.UserId, player.leaderstats.Stage.Value)
-- Saves the player's data when they leave the game
end)
You can start making your first stages now
Lava bricks
Lava bricks are an iconic part of obbies, it’s hard to find an obby that doesn’t have them. Lava bricks should be neon and red to let the player know not to touch them.
Lava bricks are pretty simple, so I won’t be explaining much about how they work.
Time to get scripting
Create a new script inside of the part you want to turn into a lava brick, as I did before, notes on how the script works will be in the code.
local part = script.Parent
-- Refers to the parent of the script
part.Touched:Connect(function(touch)
local hum = touch.Parent:FindFirstChild("Humanoid")
if hum and hum.Health > 0 then
hum.Health = 0
-- If a humanoid's health property is set to 0 they die
end
end)
If you have anything to add, are having problems, find something to be unclear or have to correct me on something I got wrong, please let me know.
In the 2nd part I’ll be going over spinning parts, instant respawning and some keyboard shortcuts such as “R” to reset.