I am trying to add multiple save slots to my game using ProfileService. This in itself is easy enough given that you can load different keys for different slots.
The issue is that I have data that I want to be synced across all different keys.
Does anyone know if this is possible, and if so, how I would go about doing it?
ProfileStore:LoadProfileAsync("Player_"..player.UserId) -- Loads different key but changes all data
You should have only one profile per player, that’s how ProfileService is intended to be used. Rather than saving multiple slots across profiles, you should only use one profile and structure it in a way that is friendly towards such behavior.
That is good to know. But as a solution, I did find out I can load two different profile stores for the same user, which (outside of GlobalUpdates) seems to be the only way I could pull off what I’m trying to achieve with the way my profiles are structured.
If this is a bad practice though and may have negative consequences overall, please let me know.
I wouldn’t necessarily label it as “bad practice”, but it is definitely unconventional and may cause unintended behavior overall, which is why I personally would not recommend it. Besides, I’m not sure what you mean by “it is only possible this way” as all you’re doing is just maintaining multiple data templates, which is entirely possible to contain in a single profile.
For this case, trying to add another template with the data to sync throws an error, mainly since the data script is not receiving that new template from the sole profile store.
Due to the fact that ProfileStore only provides the one template, the data from the other template can’t be added as well. Unless you can add multiple templates to one profileStore?
That’s not really what I mean. What you could do is “simulate” multiple templates being in one profile. The structure could look something like this:
local slotTemplate = {
money = 100,
...
}
-- Pass this into `ProfileService.New`
local template = {
currentSlot = 1, -- Default slot
slots = {
[1] = slotTemplate,
[2] = slotTemplate,
...
}
}
Now this might be a bit hard to implement into a new project as its semantics are quite different from a generic profile, but I would consider it the best way to achieve what you want by far.
Yes, it’s possible to usa that, just use a separate ProfileStore "SharedData_"..player.UserId (example) for data you want synced across all slots, and keep per slot data in individual stores then simply just load both profiles when the player joins and that should be it
Example if player clicks button 2 (Slot 2 index) then load everything with slot 2.
Edit: I do believe having multiple data stores will cause an issue with roblox, i think they limit how many total data stores you have per game, so its best to minimize this amount (Someone can correct me if i am wrong)
Correct! All you have to do is maybe modify your Manager to determine which slot to load like you could add PlayerManager.GetLoadedSlot() and return the currentSlot the player has selected like what @xnlogical said above in their code
However, this brings me back to my original issue, where I want to have some data that is synced between every slot. Unless this was already solved and I somehow missed it.
Well in that case you could just put the data in the root template rather than each slot, and just adjust your “manager code” to retrieve it in a different way.
You can determine what data you want synced by placing it outside of the slot table
local slotTemplate = {
money = 100,
...
}
-- Pass this into `ProfileService.New`
local template = {
currentSlot = 1, -- Default slot
LEVEL = 1 -- this will be a global shared data
slots = {
[1] = slotTemplate,
[2] = slotTemplate,
...
}
}
Yes all you are doing is just adding a new table its like this
local slotTemplate = {
money = 100, -- This is per slot
...
}
-- Pass this into `ProfileService.New`
local template = {
CurrentSlot = 1, -- Default slot for when player joins ?
Level = 1 -- this will be a global shared data
Slots = {
[1] = slotTemplate, -- Slot 1
[2] = slotTemplate, -- Slot 2
...
},
Settings = {
MUSIC = false,
PerformanceMode = true,
}
}
All of this will be returned under the Template you just need to reference it by using profile.Data.Settings.MUSIC → Returns false or profile.Data.Slots[1] → returns slot one.
In the data loading script you would tell what slot to receive by letting the user input their choice but for now you can hard code it
function Manager.SetCurrentSlot(Player: Player, Value: number)
local profile = Manager.Profiles[player]
if not profile then return end
profile.Data.CurrentSlot = value
end
function Manager.GetCurrentSlot(Player: Player)
local profile = Manager.Profiles[player]
if not profile then return end
return profile.Data.CurrentSlot
end
Manager.SetCurrentSlot(game.Players.MoawesomeI8, 1) -- Sets as slot one.
-- Manager.LoadSlot(game.Players.MoawesomeI8)...? If this function exists it would load everything in that slot.
This is just a bare bones example but you can modify it to your needs
As of now I currently have a function that adds folders & whatnot to the player after the single profile is loaded. Would I just have to move this code to the manager and then do:
Manager.LoadSlot(plr, CurrentSlot) as an example
?
If it’d help I can provide an example of what I mean.