cause there are other things in ProfileService
ah yes, condescension is something i look for in all of my tutorials.
then just don’t make a tutorial
(Opinion time here)
Guys, as all of you said, it is best to use what you need and what works well for your project.
I am looking to change to ProfileService since I am reading so many positive things about it, such as being fast and super reliable. But after all, it is the same DataStoreService with better-founded functions, basically added code to make it more secure and prevent glitches and errors which is always good ngl. For all of the people seeing this thread, if you have a small game that only stores a couple of values, not pets or any huge inventories, I would say the classic DataStore is fine as long as you don’t call it every 5 seconds.
You could obviously make your own module, as a lot of big games do btw to prevent exploits, I think I am going to stick to this path, a custom module since I have already added a lot of code to my datastore system. Takes time and skill as a lot of people said, but it’s a learning experience with a prize at the end. I am personally storing right now for my players, 3 classic values (Coins, Gems, Rebirths), and an inventory that stores Trails (they have names, xp, level, multiplier, rarity stored for each of them). I’ve only had one data loss and that was when I quit the studio while the data was loading (that was when I first coded my datastore), oops.
Having to change all of the system that loads and saves to a totally different one (and having to adapt the items) takes much more time than adding features to a one that works but can maybe fail if I add more stuff. If I knew about this when I started I would 100% go for ProfileService. At this point though, it is just better to code a custom one (and also learn a bunch of new stuff) and also take some code from ProfileService (give credit obv lol) and model it.
Thanks to anyone that took the time to read this post and I hope that you took a decision for your game, if you’ve already put a lot of time into your game, take how much you need to do it right.
You should only call DataStoreService when a player joins and leaves, I have no idea why someone would have to call DataStoreService all the time (which is what you might be implying).
But for anyone else reading this, if you’re just experimenting and learning, just follow from a regular tutorial. But I would suggest getting used to ProfileService as you will need it someday. Now some people might say making a custom data store system is better, although it might be a great learning experience, I still suggest focusing on being able to make a fun popular game instead of going toward the technical stuff. Even I never learned how to make my own custom data store system yet; because I don’t need to!
Agreed. I believe as long as you have the time, it is great to learn how it works and experiment with different techniques, the only problem is finding the right tutorial, it is a harder task than it should be nowadays, everyone is after subs and likes.
You should only call DataStoreService when a player joins and leaves, I have no idea why someone would have to call DataStoreService all the time (which is what you might be implying).
Some people tend to save their player’s data very often or whenever it changes which is terrible.
there isn’t <Profile>:SetAsync()
Hey anyone, is there a way to reverse data loss?
Sadly there isn’t, but if your game is small enough you can give back people’s stuff, just make sure you’re careful to not give anyone bizarre amounts of stats. When my game was experiencing data loss, I did exactly that. But after implementing a data store system with no data loss, people will forget about the data loss you had in no time.
Hey, I was wondering - how do you check if a profileservice data value has changed? I just wanted to know because im using a remote to communicate what the server knows about that player’s data to the UI.
Yeah so whenever it’s changed on the server, you want to fire that change to the client. To detect its been changed though, you need to use a callback function in a module script or regular script (a module script keeps it more organized)
local module = {}
local callbacks = {}
module.changedValue = function(name)--the name of the bind you want to change
callbacks[name]()--running the function
end
module.addCallback = function(bind,func)
callbacks[bind] = func
end
return module
--in another script
module.addCallback("Coins",function()
--what you want ran when Coins get changed
end)
--you can also set it up this way too
function changeCoins()
end
module.addCallback("Coins",changeCoins)
There’s different ways to set this up, so there isn’t a correct way to do this.
Thanks very much for this but i managed to find a function that had been implemented called :KeyInfoUpdated.
But I’m experiencing an error where the Profiles table is apparently nil, and gives the error ServerScriptService.PlayerConfig.PlayerValues:10: attempt to index nil with Instance
Here’s my code (its only like 12 lines)
local PlayerDataHandler = require(game:GetService("ServerScriptService"):WaitForChild("ProfileSystem"):WaitForChild("PlayerDataHandler"))
game:GetService("Players").PlayerAdded:Connect(function(player)
if player then
local landslot = Instance.new("NumberValue")
landslot.Parent = player
landslot.Name = "landslot"
landslot.Value = 0
local profile = PlayerDataHandler.Profiles[player] -- this is line 10, apparently Profiles is nil?
if profile ~= nil then
profile.KeyInfoUpdated("megabytes"):Connect(function()
print("megabytes changed!")
end)
end
end
end)
I’m a bit confused on this…
do this
PlayerDataHandler.Profiles[player.UserId]
It happens to me too sometimes lol
ah, I completely forgot it relied on userId…
im an idiot.
I updated the code to this and I still get the exact same error?
game:GetService("Players").PlayerAdded:Connect(function(player)
if player then
local landslot = Instance.new("NumberValue")
landslot.Parent = player
landslot.Name = "landslot"
landslot.Value = 0
end
end)
while true do
for _, player in game:GetService("Players"):GetPlayers() do
local profile = PlayerDataHandler.Profiles[player.UserId] -- this line again
if not profile then continue end
print(profile.Data.megabytes)
profile.KeyInfoUpdated:Connect(function()
print("profile updated")
end)
end
task.wait(1)
end
How can I random generate a value without it being shared to every player? My problem is everytime I generate a new value to a stat, it’s the same for everyone.
function DataHandler:RandomItemFromTbl(tbl)
local TotalWeight = 0
for Piece, Weight in pairs(tbl) do
TotalWeight = TotalWeight + Weight
end
local Chance = math.random(1, TotalWeight)
local Counter = 0
for Piece, Weight in pairs(tbl) do
Counter = Counter + Weight
if Chance <= Counter then
return Piece
end
end
end
function DataHandler:characterSetUp(player)
DataManager.Profiles[player].Data = DefaultStats --I use this so it resets everytime for rerolls
if DataManager.Profiles[player].Data.IsFirstLoad ~= true then
DataManager.Profiles[player].Data.IsFirstLoad = true
if DataManager.Profiles[player].Data.Race == "None" then
local newRace = DataHandler:RandomItemFromTbl(Info.Races)
DataManager.Profiles[player].Data.Race = newRace
end
end
end
local function playerAdded(player)
local profileData = ProfileStore:LoadProfileAsync("Player_"..player.UserId)
if profileData ~= nil then
profileData:AddUserId(player.UserId)
profileData:Reconcile()
profileData:ListenToRelease(function()
DataManager.Profiles[player] = nil
player:Kick("Data error at releasing")
end)
if player:IsDescendantOf(game.Players) then
DataManager.Profiles[player] = profileData
DataHandler:characterSetUp(player)
print(DataManager.Profiles[player].Data.Race)
else
profileData:Release()
end
else
player:Kick("Data error")
end
end
function DataHandler:Init()
for _, player in game.Players:GetPlayers() do
task.spawn(playerAdded,player)
end
game.Players.PlayerAdded:Connect(playerAdded)
game.Players.PlayerRemoving:Connect(function(player)
if DataManager.Profiles[player] ~= nil then
DataManager.Profiles[player]:Release()
end
end)
end
the table:
module.Races = {
["test1"] = 20,
["test2"] = 20,
["test3"] = 20,
["test4"] = 20,
["test5"] = 20,
["test6"] = 20,
["test7"] = 20,
["test8"] = 20,
}
Edit: DataHandler:characterSetUp(player) only runs once?