I have a saving/loading system in my game that is being rather problematic. Note that this is my second game with a DataStore system, so I’m likely making a rookie mistake.
Here’s the code for saving:
local function savestores(player)
local itemset = workspace.PlayerData:FindFirstChild(player.Name).Inventory:GetChildren()
local items = {}
for i, v in pairs(itemset) do
table.insert(items, v.Name)
end
local saved = {
cash = workspace.PlayerData:FindFirstChild(player.Name).Cash.Value,
playerequip = workspace.PlayerData:FindFirstChild(player.Name).Equips.PlayerEquip.Value,
zombieequip = workspace.PlayerData:FindFirstChild(player.Name).Equips.ZombieEquip.Value,
inventory = items
}
save:SetAsync(player.UserId, saved)
workspace.PlayerData:FindFirstChild(player.Name):Destroy()
end
This all saves correctly.
Here’s the code for the loading
local success, saved = pcall(function() save:GetAsync(player.UserId) end)
if not success or save:GetAsync(player.UserId) == nil then
print(save:GetAsync(player.UserId))
-- insert save creation code, which I'm cutting for clarity's sake
else
print(save:GetAsync(player.UserId))
-- load save
local folder = Instance.new("Folder")
folder.Name = player.Name
folder.Parent = workspace.PlayerData
local equips = Instance.new("Folder")
equips.Name = "Equips"
equips.Parent = folder
local inventory = Instance.new("Folder")
inventory.Name = "Inventory"
inventory.Parent = folder
local cash = Instance.new("NumberValue")
cash.Name = "Cash"
cash.Parent = folder
pcall(function()
if saved["inventory"] and saved["inventory"] ~= nil then -- this works perfectly, the inventory loads correctly
for i, v in pairs(saved["inventory"]) do
local item = Instance.new("BoolValue")
item.Name = v.Name
item.Parent = inventory
end
else
local item1 = Instance.new("BoolValue")
item1.Name = "Sprint"
item1.Parent = inventory
local item2 = Instance.new("BoolValue")
item2.Name = "Smell"
item2.Parent = inventory
end
end)
if saved["playerequip"] ~= nil then -- this is the problematic part.
local playerequip = Instance.new("StringValue")
playerequip.Name = "PlayerEquip"
playerequip.Value = saved["playerequip"]
playerequip.Parent = equips
else
local playerequip = Instance.new("StringValue")
playerequip.Name = "PlayerEquip"
playerequip.Value = "Sprint"
playerequip.Parent = equips
end
if saved["zombieEquip"] ~= nil then
local playerequip = Instance.new("StringValue")
playerequip.Name = "ZombieEquip"
playerequip.Value = saved["zombieequip"]
playerequip.Parent = equips
else
local playerequip = Instance.new("StringValue")
playerequip.Name = "ZombieEquip"
playerequip.Value = "Smell"
playerequip.Parent = equips
end
end
On running the game, the output window spits out a “attempt to index nil error” on the if saved["playerequip"] ~= nil then line. What’s bizarre about this is, earlier in the code, I have the system print out the loaded datastore, and, lo and behold, the correctly saved value named “playerequip” is right there! I am incredibly frustrated. What am I doing wrong?
The error occurs when you try to index a nil/unknown value, AKA;
print(nil["Name"]) -- `nil` is indexed, and since `nil` isn't a table, it throws an error
You should always re-read error messages to try and understand what they mean, but I get it if you find them a little cryptic at times.
It looks like you have made a few typos in the pcall function where you write saved, as opposed to earlier in the code where you write save without the d:
Try replacing it with
if save["inventory"] then
(There’s no point having another save["inventory"] ~= nil as nil is one of the two falsey values, along with false, meaning that the check won’t pass if it is either nil or false.)
ALSO ALSO, you can just use save.inventory instead of using save["inventory"].
Actually, this is not a typo. “save” refers to the DataStore save, “saved” refers to the player’s save in the “save”.
Thanks for the advice on the inventory thing though, but this still doesn’t fix the issue,
As the error states, saved must be a nil value. Where in your code do you set saved? Also, you should try and have more descriptive variable names. You can very easily add or forget to add the d, and it can make it more difficult for people to understand your code when you post it to #help-and-feedback:scripting-support.
For example, maybe save should be renamed playerData and saved to playerSaveSlot. It’s a lot clearer, at least for me, to know that playerData must be all the player’s save data, and playerSaveSlot is an individual save file of a session.
The code is wrapped in a pcall, so of course you will not see the error the first time. Then, the part of the code that actually shows the error is not in a pcall. If you remove the pcall, I suspect the error will occur in the first -- this works perfectly, the inventory loads correctly line.
local MyDictionary = {
a = 2,
b = " hi"
}
print("Dictionary:", MyDictionary)
print("Key C of dictionary:", MyDictionary.c) -- this prints `nil`, and does NOT give an error!
print("Key A of dictionary:", MyDoctionry.a) -- this does not print, but instead gives an error!
As you can see, despite key c not being in MyDictionary, it doesn’t give an error and instead prints nil. Then, if I misspell the dictionary as MyDoctionry instead, it gives the error “attempt to index nil with [key]” because MyDoctionry doesn’t exist as a variable and is therefore nil.
Can you point out the line you think saved is being declared in? I do not see line saying local saved = ....
Saved is declared in the pcall at the top (success, saved = --). I renamed save to datasave and saved to playersave and it still gives me the error, so it isn’t a typo. You were right about the inventory pcall() thing, though, it does give an error.