Hello!
I’m trying to make a simple obby that saves your stage progress for you to resume when you come back. I am using the DataStoreService
for this, and with it, I load the player’s stage data. Then, I use that data to set the position of their HumanoidRootPart
to the position of their stage checkpoint (plus a couple studs on the Y axis, of course).
The saving works fine.
The positioning, on the other hand, not so much. I’d say that this fails around 30% of the time.
On a normal occasion, I would spawn in and be positioned at my stage checkpoint where I left off from the last time I played the game. The leaderboard always shows the correct stage value as well.
However, 30% of the time, I spawn at the SpawnLocation
, or the default spawn for new players that join the game. This doesn’t tamper with the data, which is a good sign. All I need to do to be correctly positioned back at my saved stage is to reset my character. I don’t want to do that, though, because how would players know to reset if they spawn back at the start? They’d probably freak out about their data not loading, and there’s no way I’m putting a sign or GUI that tells them to reset their character.
Anyways, I’m sure the issue is somewhere in the server script that saves/loads the player’s stage data and positions their character. I’ve narrowed it down to the following snippet of code from that script:
player.CharacterAdded:Connect(function(character)
local humanoid,hrp = character:WaitForChild("Humanoid"),character:WaitForChild("HumanoidRootPart")
wait() -- I've tried messing with this line, but no luck.
if humanoid and hrp then
if stage.Value ~= 0 then
local part = workspace.ObbyStages:FindFirstChild(stage.Value)
hrp.CFrame = part.CFrame + Vector3.new(0,1,0)
end
end
end)
Full Script
local players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local saveDataStore = DataStoreService:GetDataStore("ClassicModeDataStore")
local function savePlayerData(player)
local success,errormessage = pcall (function()
local saveData = {}
for _,stat in pairs(player.leaderstats:GetChildren()) do
saveData[stat.Name] = stat.Value
end
saveDataStore:SetAsync(player.UserId,saveData)
end)
if not success then return errormessage end
end
players.PlayerAdded:Connect(function(player)
local stats = Instance.new("Folder")
stats.Name = "leaderstats"
stats.Parent = player
local stage = Instance.new("IntValue")
stage.Name = "Stage"
stage.Parent = stats
local data = saveDataStore:GetAsync(player.UserId)
if data then
print(player.Name.. " has joined the game. They have spawned at stage "..data.Stage..".")
for _,stat in pairs(stats:GetChildren()) do
stat.Value = data[stat.Name]
end
else
print("A new visitor, "..player.Name..", has joined the game! They do not have any data to load.")
end
player.CharacterAdded:Connect(function(character)
local humanoid,hrp = character:WaitForChild("Humanoid"),character:WaitForChild("HumanoidRootPart")
wait()
if humanoid and hrp then
if stage.Value ~= 0 then
local part = workspace.ObbyStages:FindFirstChild(stage.Value)
hrp.CFrame = part.CFrame + Vector3.new(0,1,0)
end
end
end)
end)
players.PlayerRemoving:Connect(function(player)
local err = savePlayerData(player)
if err then print(err) end
end)
game:BindToClose(function()
for _,player in pairs(players:GetPlayers()) do
local err = savePlayerData(player)
if err then print(err) end
end
wait(2)
end)
I’ve viewed a couple of topics on the DevForum to try and solve my problem, but none of the posters had an issue that happened inconsistently. I hope you guys can give me some pointers or possible solutions, as I have observed this issue for quite a while now.
Thanks!