Save your player data with ProfileService! (DataStore Module)

Yes it is possible, though highly not recommended because you’ll end up rewriting a lot of ProfileService and DataStoreService is most likely faster than Firebase.

1 Like

How can I turn off auto saving??

I need help understanding this :frowning:

This is probably a silly question but, in the future (like 3+ years) is there a chance this will ever go unsupported/deprecated? I want to use ProfileService for my game but what if Roblox designs something that makes this module become obsolete, forcing me to create a new data system, essentially wiping everyones data?

I do currently have Profile Service running through FireBase, you’ll want to adjust the rate of backup to reduce usage to stay on a free plan, fix the error for Firebase not wanting to save an empty array for GlobalUpdates by faking it or sending 0, and only consider this use for servers with 100 unique players a day at most. Any higher could hit limits to make you have to pay for a paid plan for more limits.

1 Like

There are some tutorials that were referenced in the original post that could help walk you through setting it up. I’d suggest referencing the mini tutorial on ProfileService’s GitHub page and its API on the same GitHub page alongside these video tutorials, too:



Considering loleris mentioned the following:

As long as a combination of any major changes being made to the base DataStore system and loleris deciding to cease development of this module don’t happen, I’d like to infer that there’s a high likelihood that ProfileService continues to work as intended even if it stops receiving timely updates at some point.

For reference, Datastore V2 was recently released and it seemed to focus on providing additional functionality that would work alongside what we already had access to. From what I understand, if that trend continues, ProfileService should be relatively future-proof, even if new built-in methods, functions, etc. aren’t added to this module to make it more intuitive to incorporate into existing systems.

Even if an update came along that made this module obsolete, it shouldn’t wipe any of the existing DataStore keys that have stored player data which means that it should still be able to be recovered by making use of the same keys even if you have to build up a new system for your game.

However, this is just based on my best guess so don’t take my word for it! :wink:

2 Likes

I would personally not exceed 2 profiles per player, though.

Is there a reason for this recommendation? What are the benefits of trying to cram all the user’s data into one key/value pair?
What if I’m concerned about datastore data limits per key value?

Is there a pre-defined way/function of actually connecting a player with a global update on the receiving end? Apart from passing the targets UserId in the global update data and using it to iterate through the server’s current player list, I am not sure how I would go about associating the global update with a specific player.

I watched okeanskiy’s video regarding the topic and their end result was the server receiving and parsing the information, and I was just wondering if there was a built-in function through ProfileService that I am missing that would be better than just passing the UserId as I said before and iterating through the server list.

Right now I’m just using a basic function that gets the player via their UserId that I send along with the data.

-- Localscript
ProfileStore:GlobalUpdateProfileAsync(
		"Player_".. TargetId,
		function(globalUpdates)
			globalUpdates:AddActiveUpdate({
				updateType = "FriendRequest_Incoming";
				sender = player.UserId;
				target = TargetId;
				sendTime = os.time();
			})
		end
	)
--Script
local function getPlayerByUserId(UserId)
	for _, player in pairs(Players:GetPlayers()) do
		if player.UserId == UserId then
			return player
		end
	end
end

local function handleLockedUpdate(globalUpdates, update)
	local id = update[1]
	local data = update[2]

	if data.updateType == "FriendRequest_Incoming" then
		local TargetPlayer = getPlayerByUserId(data.target)
        -- More stuff here but unnecessary to this post
		NewIncomingFriend:FireClient(TargetPlayer ) -- Only alert TargetPlayer's client to ping server for updated infomration.
	end

	globalUpdates:ClearLockedUpdate(id)
end

I suppose ultimately what I’m asking is, is there a more efficient way of doing this without needing to manually send their UserID? I only ask because I’m already targeting them on the sending-end of things by using a profile key with their UserId in it, so I wasn’t sure if I missed a native way of doing this.

1 Like

Rather than iterating over a table of players in the game. You can use game.Players:GetPlayerFromUserId to get the corresponding player object assuming they are in game.

local TargetPlayer = game.Players:GetPlayerFromUserId(data.target)

As far as I know, there is no native way to handle GlobalUpdates directly using players and objects instead of a UserId string.

1 Like

I have no idea how I overlooked game.Players:GetPlayerFromUserId. Thank you so much for the reply and your input :open_hands:

1 Like

need help. dm me

ㅤㅤ
ㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤ
ㅤㅤㅤㅤㅤㅤ

ㅤㅤ

I’m having issues with Profile Service, after setting up the data template and everything it works fine… but once the game is played by players and etc, if i added any new value to the data template it returns “nil” and errors until i totally wipe Data, How Can i Solve this issue? Since i can’t really wipe data again to just add a few values…

Look at and use profile:Reconcile() :wink:

2 Likes

Alright Let me read about it, then i will tell you if it worked ;c

Hello, I have a question. When using LoadProfileAsync if the profile isn’t found / there is no saved profile with the key, will it simply just write to the datastore / cache with the key and essentially prevent it returning a non existent profile.

If so how could I circumvent this as i want specific behaviour for when data in that certain key hasn’t been saved before.

You may use the return value of ProfileStore:ViewProfileAsync(). It will return nil if no profile is linked to the provided key.

1 Like

I’m new to ProfileService and am having an issue with some of my profile data. I have the following template:

local ProfileTemplate = {
	BestRaceTimes = {}, -- [courseNumber] = elapsedTime
	RaceCounts = {}, -- [courseNumber] = raceCount
	LogInTimes = 0,
}

This data is being updated in two ways. The first way works fine:

local function UpdateProfileLogInTimes(player, profile)
	profile.Data.LogInTimes += 1
	print(player.Name .. " has logged in " .. tostring(profile.Data.LogInTimes)
		.. " time" .. ((profile.Data.LogInTimes > 1) and "s" or ""))
end

The second way updates profile.Data but the changes aren’t getting saved to the Datastore:

local function updateRaceData(player, courseNumber, elapsedTime)
	print("PlayerProfile updateRaceData", player.UserId, courseNumber, elapsedTime)
	local profile = PlayerProfiles[player].Profile
	local bestTime = profile.Data.BestRaceTimes[courseNumber]
	if bestTime == nil or elapsedTime < bestTime then
		profile.Data.BestRaceTimes[courseNumber] = elapsedTime
	end
	if profile.Data.RaceCounts[courseNumber] == nil then
		profile.Data.RaceCounts[courseNumber] = 0
	end
	profile.Data.RaceCounts[courseNumber] += 1
end

SavepointRemoteEvent.OnServerEvent:Connect(updateRaceData)

Any idea what I am missing or doing wrong?

Hello. I have a quick question.

Is there anyway I am able to read / extract data from a profile in profile service without having to load it normally. I am also wondering how I would be able to access ALL profile entries in my profile data store.

Any help would be appreciated.

On the 3rd line, local profile = PlayerProfiles[player].Profile
I don’t think the .Profile is necessary. So you should just be able to access the data by PlayerProfiles[player].Data instead of PlayerProfiles[player].Profile.Data

Wow! A person from a discord server recommended me this, and I am very thankful because this helped a lot! Thanks, @breadbutcooler !

3 Likes