What do you want to achieve? Keep it simple and clear!
Save TotalKills Data To Player ID
What is the issue? Include screenshots / videos if possible!
ServerScriptService.Main.PlayerData:47: attempt to index number with ‘TotalKills’ - Server - PlayerData:47
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
Devfourms and videos online with data storage using
Code:
--// REMOTES \\--
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local Data = DataStoreService:GetDataStore("2")
local PlayerDataStorage = ReplicatedStorage:FindFirstChild("PlayerDataStorage")
local PlayerTemplate = PlayerDataStorage:FindFirstChild("TemplateFolder")
local PlayerDataStore = DataStoreService:GetDataStore("PlayerData")
local sessionData = {}
--// FUNCTIONS \\--
Players.PlayerAdded:Connect(function(player)
--Create new Player profile
local newProfile = PlayerTemplate:Clone()
newProfile.Name = player.Name
newProfile.Value = player.UserId
newProfile.Parent = PlayerDataStorage
local totalKillsData = newProfile.Data.TotalKills.Value
local success, playerData = pcall(function()
return PlayerDataStore:GetAsync(player.UserId)
end)
if success then
print("Data loaded: " .. player.Name)
if not playerData then
print("New player, giving default data")
playerData = {
["TotalKills"] = 0,
}
end
sessionData[player.UserId] = playerData
else
warn("Couldn't load data for: " .. player.Name)
player:Kick("Couldn't load your data, rejoin")
end
totalKillsData.Value = sessionData[player.UserId].TotalKills
end)
Players.PlayerRemoving:Connect(function(player)
local playerProfile = PlayerDataStorage:FindFirstChild(player.Name)
--Save Player data
if playerProfile then
--Save Player data
--PlayerDataStore:SetAsync(player.UserId, playerProfile.Data.TotalKills.Value)
--PlayerDataStore:SetAsync(player.UserId, playerProfile.Data.TotalDeaths.Value)
--Remove Player profile
playerProfile:Destroy()
end
end)
GlobalDataStore:SetAsync associates one key with one value. Subsequent calls to this function will override the previous value. Since the last value you set to the player’s key was TotalDeaths.Value, that will now be what is receive by your GlobalDataStore:GetAsync call. The schema your data-loading code is expecting Vs. the schema set by your data-saving code is in conflict. Your data-loading code expects the schema:
{
TotalKills: number
}
While the real data is just TotalDeaths.Value—a number. This is why when your data-loading code goes to access the “TotalKills” key of an expected table, you instead get the error "attempt to index number with ‘TotalKills’. You need to update your data-saving code to adhere to the expected schema:
local data = {
TotalKills = playerProfile.Data.TotalKills.Value,
-- ...
}
playerDataStore:SetAsync(player.UserId, data)
P.S. sessionData is redundant. You can remove it from your code
In addition to the above, you should add a return here
return player:Kick("Couldn't load your data, rejoin")
Why? After the player is kicked, the game will try to obtain the data and give the same error. It’s not really very important, but this way the console doesn’t get filled with errors.
After adding your code and tinkering around. There are no errors of the sorts, which is great and all but no data is saving. I think i missed something. Could you check this out for me?
--// REMOTES \\--
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local Data = DataStoreService:GetDataStore("2")
local PlayerDataStorage = ReplicatedStorage:FindFirstChild("PlayerDataStorage")
local PlayerTemplate = PlayerDataStorage:FindFirstChild("TemplateFolder")
local PlayerDataStore = DataStoreService:GetDataStore("PlayerData")
--// FUNCTIONS \\--
Players.PlayerAdded:Connect(function(player)
--Create new Player profile
local newProfile = PlayerTemplate:Clone()
newProfile.Name = player.Name
newProfile.Value = player.UserId
newProfile.Parent = PlayerDataStorage
local data = {
TotalKills = newProfile.Data.TotalKills.Value,
-- ...
}
PlayerDataStore:SetAsync(player.UserId, data)
local success, playerData = pcall(function()
return PlayerDataStore:GetAsync(player.UserId)
end)
if success then
print("Data loaded: " .. player.Name)
if not playerData then
print("New player, giving default data")
playerData = {
["TotalKills"] = 0,
}
end
else
warn("Couldn't load data for: " .. player.Name)
return player:Kick("Couldn't load your data, rejoin")
end
end)
Players.PlayerRemoving:Connect(function(player)
local playerProfile = PlayerDataStorage:FindFirstChild(player.Name)
--Save Player data
if playerProfile then
--Save Player data
--Remove Player profile
playerProfile:Destroy()
end
end)