DataStore2 saving/loading player position issues

Hello,

As the title suggests I’m having issues with saving a player characters position, or rather loading it, not sure what’s the problem exactly.
For a few hours now I’ve been running into this problem where the Datastore2 module succesfully saves the exact position based on the HRP, according to the print function, but whenever I load a character the Datastore2 ignores the data that was saved after the player left and just loads the default value (SpawnLake), any help would be appreciated.

Here’s my code for functions that deal with loading and saving the position

game.Players.PlayerAdded:connect(function(player)
	LoadPrimaryData(player)
	player.CharacterAdded:connect(function()
		LoadPosition(player)
		player.CharacterRemoving:connect(function(char)
			------------------Positions------------------
			local charHealth = char.Humanoid.Health
			local currPosX = char.HumanoidRootPart.Position.X
			local currPosY = char.HumanoidRootPart.Position.Y
			local currPosZ = char.HumanoidRootPart.Position.Z
			local currPos = Vector3.new(currPosX, currPosY, currPosZ)
			
			if charHealth > 0 then
				SavePosition(player, currPos)
			elseif charHealth <= 0 then
				local SpawnFirst = game.Workspace.SpawnFirst
				local SpawnKingsMercy = game.Workspace.SpawnKingsMercy
				local SpawnLake = game.Workspace.SpawnLake
				local SpawnLumber = game.Workspace.SpawnLake
				
				local FirstDist = (SpawnFirst.Position - currPos).Magnitude
				local KingsMercyDist = (SpawnKingsMercy.Position - currPos).Magnitude
				local LakeDist = (SpawnLake.Position - currPos).Magnitude
				local LumberDist = (SpawnLumber.Position - currPos).Magnitude
				
				local DistanceTable = {
					{SpawnFirst,FirstDist};
					{SpawnKingsMercy,KingsMercyDist};
					{SpawnLake,LakeDist};
					{SpawnLumber,LumberDist};
				}
				table.sort(DistanceTable, 
					function(a,b)
						return a[2] < b[2]
					end)
				for i, v in pairs(DistanceTable) do
					if i == 1 then
						currPos = Vector3.new(v[1].Position.X, v[1].Position.Y, v[1].Position.Z)
						SavePosition(player, currPos)
					end
				end
			end
		end)
		---------------------Positions-----------------
	end)
end)

local function SavePosition(player, currPos)
	if player.leaderstats:FindFirstChild("Slot") then
		local slot = player.leaderstats.Slot.Value
		local userPosX = DataStore2("PosX" .. slot, player)
		local userPosY = DataStore2("PosY" .. slot, player)
		local userPosZ = DataStore2("PosZ" .. slot, player)
		userPosX:Set(currPos.X)
		userPosY:Set(currPos.Y)
		userPosZ:Set(currPos.Z)
		print("Position saved as " .. "X-" .. userPosX:Get("None") .. " Y-" .. userPosY:Get("None") .. " Z-" .. userPosZ:Get("None"))
	end
end

local function LoadPosition(player)
	if player.leaderstats:FindFirstChild("Slot") then
		local slot = player.leaderstats.Slot.Value
		local userPosX = DataStore2("PosX" .. slot, player)
		local userPosY = DataStore2("PosY" .. slot, player)
		local userPosZ = DataStore2("PosZ" .. slot, player)
		wait(1)
		player.Character:SetPrimaryPartCFrame(CFrame.new(userPosX:Get(game.Workspace.SpawnLake.Position.X),userPosY:Get(game.Workspace.SpawnLake.Position.Y),userPosZ:Get(game.Workspace.SpawnLake.Position.Z)))
		print("Position loaded as " .. "X-" .. userPosX:Get("None") .. " Y-" .. userPosY:Get("None") .. " Z-" .. userPosZ:Get("None"))
	end
end

—Edit:
I’ve pasted the functions straight out of my script, but the load and save functions are ABOVE the player.Added function

1 Like

I haven’t checked what the full code does. But are you sure that the value of Slot is the same value on save and load?

Lets say player.Leaderstats.Slot.Value is equal to “TEST”

If you save in the DataStore of X with that value, it would be:

DataStore2("PosX" .. "TEST", player)

When loading the position, if the Slot value is not set to “TEST”, then it won’t load what you saved previously.

1 Like

the slot variable is equal to the leaderstats.Slot.Value, it’s just a leaderstats I use to determine which character slot you’re using, I don’t think that’s the issue.
Thanks for the quick reply :smiley:

1 Like

Are you getting any errors in the output console?

You should print the saved result after all the saving has been done.

On load, store the load results into a temporary variable and check what gets returned. I’m not sure what your DataStore2 function does on load.

1 Like


Nothing in the console, except for the quest error, but that’s not in the same script

Also, I forgot to mention.

If you’re testing on ROBLOX Studio, sometimes the DataStore does not have enough time to save the data before the test simulation is shut down.

You can add a BindToClose event listener to give studio a bit of time before completely shutting down.

game:BindToClose(function()
    if game:GetService("RunService"):IsStudio() then
        wait(5)
        return
    end
end)

I’ve got that lower in the code on my script, and since I’m using DataStore2 I also have the SaveInStudio bool, that’s not the issue either.

I’ve also tested it in the game itself

Ok, and finally, are you sure that “Slot” exists before executing the Load code?

You can do the following code with a timeout instead of a one time pass to check if Slot exists. As it may not be created in time.

if player.leaderstats:WaitForChild("Slot", 5) then -- 5 Seconds is optional. Leave it blank for infinite wait time. (Can hang if Slot is never found.)

Yeah you can see it in the code, the script would break if slot didn’t exist

I know, but if Slot doesn’t exist, then your code will not execute. Therefor, the position will not be loaded.

I suggest trying the following:

if player.leaderstats:WaitForChild("Slot", 5) then -- 5 Seconds is optional. Leave it blank for infinite wait time. (Can hang if Slot is never found.)
		local slot = player.leaderstats.Slot.Value
		local userPosX = DataStore2("PosX" .. slot, player)
		local userPosY = DataStore2("PosY" .. slot, player)
		local userPosZ = DataStore2("PosZ" .. slot, player)
		wait(1)
		player.Character:SetPrimaryPartCFrame(CFrame.new(userPosX:Get(game.Workspace.SpawnLake.Position.X),userPosY:Get(game.Workspace.SpawnLake.Position.Y),userPosZ:Get(game.Workspace.SpawnLake.Position.Z)))
		print("Position loaded as " .. "X-" .. userPosX:Get("None") .. " Y-" .. userPosY:Get("None") .. " Z-" .. userPosZ:Get("None"))
	end

It could very well be that Slot is just not loaded in time. Try waiting for it and see how it goes.

But wouldn’t the output tell me if the code breaks? I’m sure that slot exists whenever this function fires becouse it’s loaded before this function is called

Slot is created on player added, and the load function is called upon when the character is created

1 Like

It wouldn’t unless it errors on runtime.

FindFirstChild returns nil or an object when called. WaitForChild will wait until the object is found or hits the timeout set before continuing.

If your code errored before, then Slot was not created/loaded at the time that code was hit.

I don’t know how ROBLOX handles leaderstats internally, but it could be the culprit. Give it a shot and see how it goes. It doesn’t hurt.

I even added a line to print to tell me which slot it’s saving on, the slot is not the issue 100%

Then with the information provided. I cannot help any further. The issue may indeed lie within the DataStore2 function.

Unless the code is provided, this is the best I can do.

1 Like

I appreciate the help man, I’ll figure it out eventually :smiley:

1 Like

Oh wait, hang on. I just noticed the position loaded print is getting hit.

1 Like

Wait, why are you doing the following:

player.Character:SetPrimaryPartCFrame(CFrame.new(userPosX:Get(game.Workspace.SpawnLake.Position.X),userPosY:Get(game.Workspace.SpawnLake.Position.Y),userPosZ:Get(game.Workspace.SpawnLake.Position.Z)))

You’re using spawnlake instead of userPosX:Get("None")

1 Like

The print function seems to be printing the correct value? But the SetPrimaryPartCFrame is using SpawnLake everytime?

1 Like

Datastore2 allows you to define a default value inside those brackets, as in, if the player is joining the game for the first time, after he made his character, he would spawn at the SpawnLake part, but it should prioritize the variable:Get instead of the brackets, they’re there just in case there’s no data in the datastore, which there is as it prints out from the data store itself right after saving

1 Like