Anyone know why this simple script is not working?

local workspace = game:GetService("Workspace")
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")

local checkpointsFolder = workspace:FindFirstChild("Checkpoints")
if checkpointsFolder then
	local currentCheckpoint = 1
	local arrow = nil

	local function createArrow()
		local nextCheckpoint = checkpointsFolder:FindFirstChild(tostring(currentCheckpoint + 1))

		if nextCheckpoint then
			local billboard = Instance.new("BillboardGui")
			billboard.Parent = nextCheckpoint
			billboard.AlwaysOnTop = true
			billboard.Size = UDim2.new(0, 100, 0, 100)
			billboard.StudsOffset = Vector3.new(0, 3, 0)

			arrow = Instance.new("ImageLabel")
			arrow.Parent = billboard
			arrow.Image = "http://www.roblox.com/asset/?id=14889663526"
			arrow.Size = UDim2.new(1, 0, 1, 0)
			arrow.ImageColor3 = Color3.new(1, 0, 0)

			local direction = (nextCheckpoint.Position - humanoidRootPart.Position).unit
			local angle = math.atan2(direction.x, direction.z) - math.atan2(humanoidRootPart.CFrame.lookVector.x, humanoidRootPart.CFrame.lookVector.z)
			arrow.Rotation = math.deg(angle) + 180
		else
			
			print("No next checkpoint found")
			return
		end
	end

	createArrow()

	checkpointsFolder.ChildAdded:Connect(function(child)
		local childName = tonumber(child.Name)
		if childName and childName == currentCheckpoint then
			currentCheckpoint = childName + 1
			createArrow()
		end
	end)
end

anyone know why this script is not working? i want to make a script that has an arrow pointing to the next checkpoint. when you reach the checkpoint it goes to the next checkpoint. nothing is printing in the output

No condition has actually been met to assign the next checkpoint, as an example if I were to walk to the checkpoint the arrow will do nothing but show the rotation of the next checkpoint.

Instead of doing “ChildAdded” you instead should be either checking constantly to see if the player is near the checkpoint OR checking if a collision occurs within the current checkpoint.

By your current code, if a new checkpoint was added anyway it would break as children would be iteratively added. You would create an arrow, and instantly the next arrow would be generated. This can be proven through running createArrow() after your child added function.