I’m using some data from ProfileService to decide what accessories the player spawns in with. This means that I need the data ASAP.
I’m running into numerous issues with trying to use the data before it’s loaded in. Below is my attempt at resolving this issue.
game.Players.PlayerAdded:Connect(function(Player)
game.StarterPlayer.LoadCharacterAppearance = false
local profile = nil
Player.CharacterAdded:Connect(function(Character)
local attempts = 0
while profile == nil do
profile = Manager.Profiles[Player]
task.wait(3)
attempts += 1
if attempts >= 8 then
Player:Kick("An error loading your data occured. Please try reconnecting!")
break;
end
end
LoadPlayerAccessories(Player)
end)
end)
This while loop approach is really not an appropriate solution, and is more of a bandaid on the problem. What would be a better way to ensure the data is loaded in before I try to use it?
i dont see anything wrong with the script but, set CharacterAdded as a function and fire it just when the player joins and the CharacterAdded thing
and define the profile variable
game.Players.PlayerAdded:Connect(function(Player)
game.StarterPlayer.LoadCharacterAppearance = false
local profile = Manager.Profiles[Player]
local function CharacterAdded(Character)
local attempts = 0
while not profile do
profile = Manager.Profiles[Player]
task.wait(3)
attempts += 1
if attempts >= 8 then
Player:Kick("An error loading your data occured. Please try reconnecting!")
break
end
end
LoadPlayerAccessories(Player)
end
CharacterAdded(Player.Character or Player.ChildAdded:Wait())
Player.CharacterAdded:Connect(CharacterAdded)
end)
I would recommend moving this character added function to your data loading script. Set up your script like this:
Load the data (which will yield until finished), connect the character added, and finally run the character added on the player’s existing character if their character loaded before their data.
Move everything you want to do to the handler itself. Something like this:
local function PlayerAdded(Player)
local Profile = ProfileStore:LoadProfileAsync("Player_"..Player.UserId)
if not Profile then
Player:Kick(DataErrorMessage)
return
end
Profile:AddUserId(Player.UserId)
Profile:Reconcile()
Profile:ListenToRelease(function()
Manager.Profiles[Player] = nil
Player:Kick(DataErrorMessage)
end)
if Player:IsDescendantOf(Players) then
Manager.Profiles[Player] = Profile
else
Profile:Release()
end
-- Things to initialize before being ready to play
FS_Character.OnCharacterAdded(Player) -- this is a modulescript. You can just write a Player.CharacterAdded event directly here if you want.
end
while profile == nil do
profile = Manager.Profiles[Player]
wait(3)
attempts += 1
end
This code isn’t doing what you think it’s doing. It’s not waiting 3 seconds, it’s waiting until profile is nil, then 3 seconds, then it’s waiting until profile is nil, then 3 seconds, then profile is not nil so it exits the loop.
I’m not sure what Manager.Profiles[Player] is, but if it’s an asynchronous function that returns a Promise you should be able to do this: local profilePromise = Manager.Profiles[Player]
local profile = profilePromise:Await()
If it’s not a Promise then you should make it one.
It’s a serversided dictionary, which holds the data of the current players in the game. The data is session locked to that specific server, until ProfileService has released the profile. Release will happen after data is saved - upon player removal or shutdown of the server.