I'm trying to create a DataStore system that saves and loads number values when a player joins or leaves the game. To accomplish this, I clone a model with number values inside of it into ServerStorage when a player joins. Then, I rename the model to (player's name)Data. I'm running into a problem where the remote function is not returning the model, therefore not allowing me to manipulate the values.
First, I start by cloning the 'Data' model already inside of ServerStorage. NOTE: The 'default' table is indexed if the player has never player before. For example, if they haven't played before (no DataStore key is found), set the cash to 50. Otherwise, load the data.
local storage = game.ServerStorage local service = game:GetService("DataStoreService"):GetDataStore("ForeverDevStats") local default = { cash = 50 } game.Players.PlayerAdded:connect(function(player) local data = storage.Data:clone() data.Parent = storage data.Name = player.Name .. "Data" for _, store in ipairs(data:GetChildren()) do --load the saved values, or set to the default value store.Value = service:GetAsync(tostring(player.userId) .. store.Name:lower()) or default[store.Name:lower()] end end)
Next, I want to attach each value to a .Changed event (!!in a different script!!), so I can use them accordingly in my game. I do this by retrieving the data model through the use of a remote function.
The remote function is located in a model in Workspace, and is called 'GetPlayerData'. The code is as follows:
function script.Parent.GetPlayerData.OnServerInvoke(player) return game.ServerStorage:FindFirstChild(player.Name .. "Data") end
It is important that I note that the function does in fact find the data model, HOWEVER, it returns nil. Here is the script where I try to attach each value to a .Changed event:
--local script local screen = script.Parent:WaitForChild("ScreenGui") local displays = { cash = screen:WaitForChild("Cash") } --inefficient, but I want to make sure the data exists repeat wait() until Workspace.Functions.GetPlayerData:InvokeServer() local data = Workspace.Functions.GetPlayerData:InvokeServer() --the error is that 'data' is a nil value for _, storage in ipairs(data:GetChildren()) do storage.Changed:connect(function(value) --manipulate a gui (not important) displays[storage.Name:lower()].Output.Text = displays[storage.Name:lower()].StringOutput.Value:gsub("VALUE", tostring(value)) end) end
For some reason, the remote function is returning a nil value instead of the player's data model. How can I fix this? Thanks in advance.
Because none of the objects in ServerStorage replicate to the client. You should put them in ReplicatedStorage if you want them to be accessible to both server and client scripts.