Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

How to save string values through data stores?

I am not too experienced with data stores, and i am having trouble saving my player's string value data. And yes, i tried the wiki and stuff but it still doesnt seem to work.

This is what i tried so far:

local ds = game:GetService("DataStoreService"):GetDataStore("Stats")
local stats={"Slot1","Slot2","Slot3","Slot4","Slot5","Slot6","Slot7","Slot8","Slot9","Slot10"}
game.Players.PlayerAdded:connect(function(plyr)
	local a=Instance.new("StringValue")
	a.Parent=plyr
	a.Name="Characters"
	for i=1,#stats do
		local stat=Instance.new("StringValue")
		stat.Parent=a
		stat.Value = "None"
		stat.Name=stats[i]
	end
	local child=plyr.Characters:GetChildren()
	for i=1, #child do
		child[i].Value=ds:GetAsync(plyr.userId..child[i].Name)
	end
end)

game.Players.PlayerRemoving:connect(function(plyr)
	local child=plyr.Characters:GetChildren()
	for i=1, #child do
		child[i].Value=ds:SetAsync(plyr.userId..child[i].Name,child[i].Value)
	end
end)

I get this from Output:

18:19:12.490 - ServerScriptService.DataStore:16: bad argument #3 to 'Value' (string expected, got nil)
18:19:12.491 - Stack Begin
18:19:12.491 - Script 'ServerScriptService.DataStore', Line 16
18:19:12.492 - Stack End

If someone can help then i would be greatly appreciated. Thanks!

1 answer

✓ Accepted answer

The problem here is line fifteen where you put child[i].Name. Child is a table containing the children of the Characters instance and does not contain numerical indices.

In order to fix this, iterate through the children using a generic for loop so that you can get the value directly from each pass of the loop. This would be implemented like so:

for i , v in pairs(child) do
	v.Value = ds:GetAsync(ply.userID..v.Name)
end

Because data stores are stored in the Roblox servers, they are prone to error due to problems like connectivity. For this reason, your call to GetAsync should be wrapped in a pcall() function to handle any possible error correctly. In addition, a player joining for the first time will have a nil value for the player's corresponding data store. You should check if the value from the data store exists or not before using it. If it doesn't, set the value to some sort of default. Your final listener function to the PlayerAdded event should be this:

game.Players.PlayerAdded:Connect(function(plyr)
	local a=Instance.new("StringValue")
	a.Parent=plyr
	a.Name="Characters"
	for i=1,#stats do
		local stat=Instance.new("StringValue")
		stat.Parent=a
		stat.Value = "None"
		stat.Name=stats[i]
	end

	for i , v in pairs(plyr.Characters:GetChildren()) do
		local success , value = pcall(function ()
			return ds:GetAsync(plyr.userId..v.Name)
		end)
		if success then
			if value then
				v.Value = value
			else
				--Player is joining for the first time
				--and datastore is empty
			end
		else
			--handle error here
		end
	end
end)

5 comments

0

I tried this out, but it is for some reason still giving me the same error in output, but now in line 20 (v.Value = value). I cant seem to find whats wrong with this :(

0

Try printing v.Value and value variable and look at the results.

0

v.Value prints as "None", and value prints as "Nil", so that may be the problem

0

I think the problem is that when a player joins for a first time, the corresponding data store for that player is nil. This is why the value variable equals nil. Let me fix this in the answer.

0

Okay, i fixed it Lol. It turns out i had to check if it was "nil", and then if so then do: value=ds:SetAsync(plyr.UserId..v.Name,"None"). Thanks a lot for the help!

This discussion is preserved as it was. New answers, comments, and votes are closed.