DataStore Values not loading

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? I want to successfully load the saved data

  2. What is the issue? The data saves but upon rejoining the data appears as “0” (or other default value)

DataStore script

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("AvatarData")
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Data = {
	Face = 0;
	Shirt = 0;
	Pant = 0;
	Hat = 0;
	Torso = {5, 105, 174};
	Arms = {245, 206, 44};
	Head = {245, 206, 44};
	Legs = {165, 190, 69}
}

local function color3ToDictionary(color3Object)
    assert(typeof(color3Object) == "Color3", "Color3 expected")

    local color3Dictionary = {
        R = color3Object.R,
        G = color3Object.G,
        B = color3Object.B,
    }

    return color3Dictionary
end


local playersavetable = {};

local function loadStarterData(Player)
		local CharData = Instance.new("Folder")
		CharData.Name = "AvatarConf"
		CharData.Parent = Player
		for statname, statvalue in pairs(Data) do
			if type(statvalue) == 'number' then
			local intvalue = Instance.new("IntValue")
			intvalue.Name = statname
			intvalue.Value = statvalue
			intvalue.Parent = CharData
			else
			local colorvalue = Instance.new("Color3Value")
			colorvalue.Name = statname
			colorvalue.Value = Color3.fromRGB(statvalue[1],statvalue[2],statvalue[3])
			colorvalue.Parent = CharData
		end
	end
end

local function loadData(player)
	local Data
	local s, e = pcall(function()
	Data = DataStore:GetAsync('UserId'..player.UserId)
	end)
	
	if s then 
		print (player.Name.."Data loaded")
	else
		print(player.Name.."Data failed to load")
	end
	
	if Data then
		for statname, statvalue in pairs(Data) do
			player.AvatarConf[statname].Value = statvalue
		end
		print(player.Name.."Data has been loaded")
	else
		print(player.Name.."No data found! generating..")
		end
	end

local function saveData(player)
	--if RunService:IsStudio() then return end
	local Data = {}
	for _, stat in ipairs(player.AvatarConf:GetChildren()) do
    if stat:IsA("Color3Value") then
        Data[stat.Name] = color3ToDictionary(stat.Value)
    else
        Data[stat.Name] = stat.Value
    end
end
	local s, e = pcall(function()
		DataStore:SetAsync('UserId'..player.UserId, Data)
	end)
		if s then 
	print(player.Name.."Data has been saved")
		else
	warn (player.Name.."Data failed to save"..e)
	end
end

ReplicatedStorage.SaveEvent.OnServerEvent:Connect(function(player)
 saveData(player)	
end)

Players.PlayerAdded:Connect(function(player)
	playersavetable[player] = tick()
	loadStarterData(player)
	loadData(player)
end)

Players.PlayerRemoving:Connect(function(player)
	saveData(player)
end)

Button to change data (LocalScript)

script.Parent.MouseButton1Click:connect(function()
		game.Players.LocalPlayer.AvatarConf.Hat.Value = 66
	end
) 

Lastly here is the code for the button that calls the save function

script.Parent.MouseButton1Click:connect(function()
	game.ReplicatedStorage.SaveEvent:FireServer()
	end
) 
  1. What solutions have you tried so far? Well I tried looking over my previous post but that didn’t help much because it was about saving rather then loading.

Oh and upon load this error code displays: " [ServerScriptService.Script:66: bad argument #3 to ‘Value’ (Color3 expected, got table)"

This doesn’t fix the error but you can’t change the player’s stat values on the client you have to do it on the server.

I was told that before and thats why I added the remote event

script.Parent.MouseButton1Click:connect(function()
	game.Players.LocalPlayer.AvatarConf.Hat.Value = 66
end
) 

you need to add a remote event to change that on the server

I tried adding the remote event to that script but it still didnt work. I should say that I tapped the button to change the value followed by the save button (before I tried this)

The button you created to change the Hat value only changes it on the Client. You will need a Remote Event for that. Here are the Steps I did:

1.) I created a Remote Event in Replicated Storage and named it Color. From the LocalScript I fired the Event and at the end of the Data script (under the save remote) I put a OnServerEvent.

2.) To prevent the error on line 66 I put a if Statement to check if the value is a number. If it is a number the value will load if not a Color3 Value will be created with the 3 numbers in the table.

Local script for the button to change the Value.

script.Parent.MouseButton1Click:connect(function()
	game.ReplicatedStorage.Color:FireServer()
end)

Server Script.

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("AvatarData")
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local Data = {
	Face = 0;
	Shirt = 0;
	Pant = 0;
	Hat = 0;
	Torso = {5, 105, 174};
	Arms = {245, 206, 44};
	Head = {245, 206, 44};
	Legs = {165, 190, 69}
}

local function color3ToDictionary(color3Object)

    local color3Dictionary = {
        R = color3Object.R,
        G = color3Object.G,
        B = color3Object.B,
    }

    return color3Dictionary
end


local playersavetable = {};

local function loadStarterData(Player)
		local CharData = Instance.new("Folder")
		CharData.Name = "AvatarConf"
		CharData.Parent = Player
		for statname, statvalue in pairs(Data) do
			if type(statvalue) == 'number' then
			local intvalue = Instance.new("IntValue")
			intvalue.Name = statname
			intvalue.Value = statvalue
			intvalue.Parent = CharData
			else
			local colorvalue = Instance.new("Color3Value")
			colorvalue.Name = statname
			colorvalue.Value = Color3.fromRGB(statvalue[1],statvalue[2],statvalue[3])
			colorvalue.Parent = CharData
		end
	end
end

local function loadData(player)
	local Data
	local s, e = pcall(function()
	Data = DataStore:GetAsync('UserId'..player.UserId)
	end)
	
	if s then 
		print (player.Name.."Data loaded")
	else
		print(player.Name.."Data failed to load")
	end
	
	if Data then
		for statname, statvalue in pairs(Data) do
			if type(statvalue) == "number" then
			player.AvatarConf[statname].Value = statvalue
			else
			player.AvatarConf[statname].Value = Color3.new(statvalue.R,statvalue.G,statvalue.B)
			end
		end
		print(player.Name.."Data has been loaded")
	else
		print(player.Name.."No data found! generating..")
		end
	end

local function saveData(player)
	--if RunService:IsStudio() then return end
	local Data = {}
	for _, stat in ipairs(player.AvatarConf:GetChildren()) do
    if stat:IsA("Color3Value") then
		Data[stat.Name] = color3ToDictionary(stat.Value)
    else
        Data[stat.Name] = stat.Value
    end
end
	local s, e = pcall(function()
		DataStore:SetAsync('UserId'..player.UserId, Data)
	end)
		if s then 
	print(player.Name.."Data has been saved")
		else
	warn (player.Name.."Data failed to save"..e)
	end
end

ReplicatedStorage.SaveEvent.OnServerEvent:Connect(function(player)
 saveData(player)	
end)

ReplicatedStorage.Color.OnServerEvent:Connect(function(player)
	game.Players[player.Name].AvatarConf.Hat.Value = 66
end)

Players.PlayerAdded:Connect(function(player)
	playersavetable[player] = tick()
	loadStarterData(player)
	loadData(player)
end)

Players.PlayerRemoving:Connect(function(player)
	saveData(player)
end)

It would be a good Idea to save data when the player is leaving and use BindToClose incase of shutdown.

do I have to create separate remote events for every thing that changes variables? that would be like 50+ remote events.

RobloxScreenShot20191204_215013057|690x370

I would have to have a lot of separate remote events (just for the face menu) if this is the case. Isn’t there a way I could change the LocalScript to a normal script and still change data variables?

I made a remote event for Items in Replicated Storage. I moved the Server Side Remote event code from the Data script to a separate script to keep it from being messy and easier to find.

When you Fire the Remote Event from the Local Script you can add Parameters.

script.Parent.FocusLost:connect(function()
	game.ReplicatedStorage.Items:FireServer("Shirt", script.Parent.Text)
end)

In the Parameters I put the Item which is “Shirt” and the 2nd Parameter is the number that is typed in the text box.

The Server Script:

game.ReplicatedStorage.Items.OnServerEvent:Connect(function(player,item,number,color)
	if item == "Hat" then
		game.Players[player.Name].AvatarConf.Hat.Value = number
		print("Set Hat to " .. number)
	else if item == "Face" then
		game.Players[player.Name].AvatarConf.Face.Value = number
		print("Set Face to " .. number)
	else if item == "Shirt" then
		game.Players[player.Name].AvatarConf.Shirt.Value = number
		print("Set Shirt to " .. number)
		end
	end
end
end)

I added a few to show an Example this just changes the number to what is typed and prints it. If the items cost money you will need to add a server check to make sure this doesn’t get exploited.Test.rbxl (28.0 KB) This is the rbxl file of the test I used.

Mine doesn’t have you enter text and i’m not sure where to start modifying, mine uses a GUI with a selection of 15 (and counting) hats. so I’m kinda lost but don’t worry I will think of something and I will mark your previous reply as the solution!

Thanks for the help :smiley: