I’ve been spending a lot of time trying to figure out how to implement ProfileService into my game with character customization. I’m attempting to save/load the money and level that the player has, as well as their character’s hair, face, and skin color. I save the money, level, hair, and face as integer values (for hair and face it is the asset ID) as well as each individual RGB value (Color3.R, Color3.G, Color3.B) for the skin inside a table in a module script.
The player customizes their character from a screen GUI which fires server events to change their character appearance. There is no accessing the player profile here. The character will have already loaded in with either their saved appearance (if they have one) or the default which is stored in a HumanoidDescription.
From a distance, it seems to work perfectly well… until you join back into the game to see that the player has no saved profile. Initially, I thought that when a player joins for the very first time their data does not get saved for some reason, but now I’m not so sure. I’m also talking about in-game, and not in-studio testing.
This is the code I use for my module script that requires ProfileService. This is named “DataManager” in ServerScriptService.
local ProfileService = require(script.ProfileService)
local RS = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local Profiles = {}
local ProfileStore = ProfileService.GetProfileStore(
"PlayerData", {
-- profile template defaults
SkinR = 239,
SkinG = 215,
SkinB = 167,
Hair = 16630147,
Face = 20418658,
Money = 100,
Level = 0
}
)
local function playerDataLoaded(player) -- initializes the player leaderstats based on what their profile contains
local profile = Profiles[player]
local folder = Instance.new("Folder")
folder.Name = "leaderstats"
folder.Parent = player
local level = Instance.new("IntValue")
level.Name = "Tier"
level.Value = profile.Data.Level
level.Parent = folder
local money = Instance.new("IntValue")
money.Name = "Money"
money.Value = profile.Data.Money
money.Parent = folder
spawn(function()
while true do
local profile = Profiles[player]
if profile ~= nil then
level.Value = profile.Data.Level
money.Value = profile.Data.Money
end
wait (0.1)
end
end)
end
local function onPlayerAdded(player)
local profile = ProfileStore:LoadProfileAsync(
"Player_" .. player.UserId, -- this is the key I use
"ForceLoad"
)
if profile ~= nil then
profile:ListenToRelease(function()
Profiles[player] = nil
player:Kick("Your saved data has been loaded remotely. Please rejoin.")
end)
if player:IsDescendantOf(Players) then
Profiles[player] = profile
playerDataLoaded(player, profile)
else -- player left before profile loaded
profile:Release()
end
else -- profile does not exist
player:Kick("Unable to load player data. Please rejoin the game.")
end
end
-- player before this script ran:
for _, player in ipairs(Players:GetPlayers()) do
spawn(function()
onPlayerAdded(player)
end)
end
Players.PlayerAdded:Connect(onPlayerAdded)
Players.PlayerRemoving:Connect(function(player)
local profile = Profiles[player]
if profile ~= nil then
profile:Release()
end
end)
function Profiles:Get(player) -- i don't really use this. It's easier to access the module's table DataManager[player]
local profile = Profiles[player]
if profile then
return profile.Data
else
print("No profile found.") -- this is what I keep seeing over and over and over
end
end
return Profiles
The above code seems to work. But when I try to retrieve the player’s profile from another server script, the profile is never found. I’ve tried playing the game (outside studio), leaving, then rejoining a few minutes later to see if the profile would be loaded the second time, but no.
Here is the server script that requires the above module and handles the character appearance (has a HumanoidDescription as a child to apply to the player’s character when the values have been edited appropriately):
local Players = game:GetService("Players")
local RS = game:GetService("ReplicatedStorage")
local SS = game:GetService("ServerScriptService")
local DataManager = require(game.ServerScriptService.DataManager)
local starterDescription = script:FindFirstChild("StarterDescription") -- premade humanoiddesc inside this script
Players.PlayerAdded:Connect(function(player)
local savedCustomization = DataManager[player]
if savedCustomization ~= nil then
local newColor = Color3.new(savedCustomization.Data.SkinR, savedCustomization.Data.SkinG, savedCustomization.Data.SkinB)
starterDescription.HeadColor = newColor
starterDescription.TorsoColor = newColor
starterDescription.LeftArmColor = newColor
starterDescription.RightArmColor = newColor
starterDescription.RightLegColor = newColor
starterDescription.LeftLegColor = newColor
starterDescription.HairAccessory = savedCustomization.Data.Hair
starterDescription.Face = savedCustomization.Data.Face
else
print("There was no data for "..player.Name) -- this is also what I keep seeing
end
local function CharacterAdded(char)
local humanoid = char:FindFirstChild("Humanoid")
humanoid.Died:Connect(function()
starterDescription = char.Humanoid:GetAppliedDescription() or starterDescription -- handles the player appearance, whether or not it exists
player:LoadCharacterWithHumanoidDescription(starterDescription)
end)
end
if player.Character ~= nil then
CharacterAdded(player.Character)
end
player.CharacterAdded:Connect(CharacterAdded)
player:LoadCharacterWithHumanoidDescription(starterDescription)
end)
I’ve followed the tutorials included in the ProfileService post and I’ve done what I think is right to make it fit my needs. It seems like I’ve deleted my code and restarted several times now to no avail.
Also, I’m under the impression that anytime data in a player’s profile is edited, it is saved. This makes me think that my problem has to do with retrieving, and not applying, the player’s data.
Any help or advice on this issue would be greatly appreciated. I’m excited to implement ProfileService, but my lack of expertise has caught up with me.