Better way of making checkpoint system?

Checkpoint system.

local Checkpoints = game.Workspace.Game.Obby.Checkpoints
local Debounce = false

for index, value in pairs(Checkpoints:GetChildren()) do
	if value.Touched:Connect(function(part)
			local partParent = part.Parent
			local player = game.Players:GetPlayerFromCharacter(partParent)
			local leaderstats = player.leaderstats
			local playerStage = leaderstats.Stage
			local playerPoints = leaderstats.Points
			if tonumber(value.Name) == playerStage.Value + 1 then
				if not Debounce then
					Debounce = true
					print("WHAT IS THIS SORCERY?")
					--value.BrickColor = BrickColor.new(0,255,0)
					playerStage.Value = playerStage.Value + 1
					playerPoints.Value = playerPoints.Value + 5
					wait()
					Debounce = false
					if player then
						value.BrickColor = BrickColor.new(0,255,0)
					end
					if player.MembershipType == Enum.MembershipType.Premium then
						print("Premium you get +5 points!")
						-- Take some action specifically for Premium members
						playerPoints.Value = playerPoints.Value + 5
					else
						print("Non premium you just get + 5")
					end
				end
			end
		end) then
	end
end

You can make use of guard clauses and just tidying up your code in general:

--//Services
local Players = game:GetService("Players")

--//Variables
local Checkpoints = workspace.Game.Obby.Checkpoints

--//Tables
local Debounces = {}

--//Functions
local function InitializeCheckpoint(checkpoint)
	local checkpointNumber = tonumber(checkpoint.Name)
	
	checkpoint.Touched:Connect(function(hit)
		local player = Players:GetPlayerFromCharacter(hit.Parent)
		
		if not player or Debounces[player] then
			return
		end
		
		local leaderstats = player.leaderstats
		
		if leaderstats.Stage.Value + 1 == checkpointNumber then
			Debounces[player] = true
			
			checkpoint.BrickColor = BrickColor.new(0, 255, 0)
											
			leaderstats.Stage.Value += 1
			leaderstats.Points.Value += 5
			
			if player.MembershipType == Enum.MembershipType.Premium then
				print("Premium you get +5 points!")
				
				--//Take some action specifically for Premium members
				leaderstats.Points.Value += 5
			end
			
			task.wait()
			Debounces[player] = false
		end
	end)
end

for i, checkpoint in ipairs(Checkpoints:GetChildren()) do
	InitializeCheckpoint(checkpoint)
end

I would use the CollectionService along with object oriented programming for the checkpoints (see CollectionService).

local CollectionService = game:GetService("CollectionService")

------------------------------------------------------------------------------
-- In this section of the script, we define a Checkpoint class. This could be placed in
-- its own independent ModuleScript.

-- For more information on this class pattern, check out
-- the object-oriented programming chapter in Programming in Lua:
-- https://www.lua.org/pil/16.html

local Checkpoint = {}
Checkpoint.__index = Checkpoint

function Checkpoint.new(part)
    -- Create a table which will act as our new Checkpoint object.
    local self = {}
    -- Setting the metatable allows the table to access
    -- the SetOpen, OnTouch and Cleanup methods even if we did not
    -- add all of the functions ourself - this is because the
    -- __index metamethod is set in the Checkpoint metatable.
    setmetatable(self, Checkpoint)

    -- Keep track of some Checkpoint properties of our own
    self.part = part
    self.debounce = false

    -- Initialize a Touched event to call a method of the Checkpoint
    self.touchConn = Checkpoint.Touched:Connect(function (...)
        self:OnTouch(...)
    end)

    -- Print a message so we know when Checkpoints are initialized
    print("Initialized Checkpoint: " .. Checkpoint:GetFullName())

    return self
end

function Checkpoint:OnTouch(part)
    if self.debounce then return end

    self.debounce = true

    -- do something
end

function Checkpoint:Cleanup()
    self.touchConn:disconnect()
    self.touchConn = nil
end

------------------------------------------------------------------------------
-- In this section of the script, we want to listen for objects with the Checkpoint
-- tag. When we find one, create a new Checkpoint and keep track of it. When the Checkpoint
-- tag is removed, we'll find the Checkpoint we created and destroy it.

local checkpoints = {}

local checkpointAddedSignal = CollectionService:GetInstanceAddedSignal(Checkpoint.TAG_NAME)
local checkpointRemovedSignal = CollectionService:GetInstanceRemovedSignal(Checkpoint.TAG_NAME)

local function onCheckpointAdded(Checkpoint)
    if Checkpoint:IsA("BasePart") then
        -- Create a new Checkpoint object and save it
        -- The Checkpoint class will take over from here!
        checkpoints[Checkpoint] = Checkpoint.new(Checkpoint)
    end
end

local function onCheckpointRemoved(Checkpoint)
    if checkpoints[Checkpoint] then
        -- Clean up an already-existing Checkpoint
        checkpoints[Checkpoint]:Cleanup()
        checkpoints[Checkpoint] = nil
    end
end

-- Listen for existing tags, tag additions and tag removals for the Checkpoint tag
for _,inst in pairs(CollectionService:GetTagged(Checkpoint.TAG_NAME)) do
    onCheckpointAdded(inst)
end

CheckpointAddedSignal:Connect(onCheckpointAdded)
CheckpointRemovedSignal:Connect(onCheckpointRemoved)

5 Likes