Tagging Checkpoints... Gone Wrong?

A quick rundown of this script: Upon joining for the first time, you’ll hit your first checkpoint and you’ll be assigned an instance named “CheckpointData” (as none exists for each player upon joining), and upon hitting a new checkpoint (order does not matter, even ones you’ve hit previously) the data will be updated so you’ll spawn at that new checkpoint. Upon leaving, the data is erased in a different script, so it can be created again on the next join. This has worked perfectly for me for a long time.

I’m currently trying to save myself the future issue of having multiple of this same script for every checkpoint that needs this script. So, of course I go to the amazing godsend of a plugin, which I’ve used before, instance tagging. This time however, there’s an issue.

All I changed in this checkpoint script was making it apply the script to all tagged checkpoints, rather than having the script in each individual checkpoint. However, with this small change, the CheckpointData no longer seems to update for new checkpoints. The first checkpoint still creates the data, and works as intended whenever you reset (there is no spawn point in the game, so this confirms that the checkpoint works), but upon touching any new checkpoint and resetting, you spawn back at the first one.

Not really sure what I have to change here, as I’m really not too sure why having the script work on the tagging system breaks the CheckpointData, so any and all advice would be greatly appreciated.

local CollectionService = game:GetService("CollectionService")

local Checkpoints = CollectionService:GetTagged("Checkpoints")

for _, spawn in pairs(Checkpoints) do 
	spawn.Touched:connect(function(hit)
		if hit and hit.Parent and hit.Parent:FindFirstChild("Humanoid") then
			local player = game.Players:GetPlayerFromCharacter(hit.Parent)
			local checkpointData = game.ServerStorage:FindFirstChild("CheckpointData")
			if not checkpointData then
				checkpointData = Instance.new("Model", game.ServerStorage)
				checkpointData.Name = "CheckpointData"
			end
			
			local checkpoint = checkpointData:FindFirstChild(tostring(player.userId))
			if not checkpoint then
				checkpoint = Instance.new("ObjectValue", checkpointData)
				checkpoint.Name = tostring(player.userId)
				player.CharacterAdded:connect(function(character)
					wait()
					character:WaitForChild("HumanoidRootPart").CFrame = game.ServerStorage.CheckpointData[tostring(player.userId)].Value.CFrame + Vector3.new(0, 4, 0)
				end)
			end
			checkpoint.Value = spawn
		end
	end)
end

It should be emphasized that the entirety of the script, save for the first three lines, is exactly the same as the original script.

Previously, I defined “spawn” as

local spawn = script.Parent

and that was the only line of code above the Touched function.

DISCLAIMER: I should mention that I did not write the original script myself, however I forgot where I got it from.

Have you tried printing spawn?

When printing spawn, the name of that particular checkpoint is printed. Seems to work for each checkpoint, and when printing spawn in the original script, the same result is produced.

New discovery: Both the original script and the modified script for tagged instances WORK in a script test world I have, however in the actual game I’m working on, neither seem to work despite the scripts being exact uploads of the originals used in the test world.

Chances are, there’s some silly mistake I’ve made somewhere.

Simple issue/solution: had a (recently made) script that teleported the player on join to a part that dropped you onto the first checkpoint, however it kept doing so on death rather than only one time on join.