Hi all,
I’ve run into an odd bug that is fixed by using a wait() statement.
This is a server script
if Works and SavedPlayerData ~= nil then
CurrentPlayerData[PlayerID] = GameDataAndScripts.CopyTables(SavedPlayerData)
CurrentRockAmount[PlayerID] = 0
local GoldAmount = CurrentPlayerData[PlayerID][1]
local BackpackType = CurrentPlayerData[PlayerID][2]
local PickaxeType = CurrentPlayerData[PlayerID][3]
PlayerLoadData:FireClient(Player , GoldAmount, BackpackType, PickaxeType)
RunService.Heartbeat:Wait()
GivePlayerItem(Player, PickaxeType)
break
end
The above script loads data from a datastore and copies it to regular table. The function at the bottom (GivePlayerItem()) gives the player their starting pickaxe from ServerStorage.
local function GivePlayerItem (Player, Item)
local NewItem = ServerStorageService:WaitForChild(Item):Clone()
NewItem.Parent = Player:WaitForChild("Backpack")
end
Not sure if I need those two WaitForChild(), can someone tell me?
The initial bug was that the Pickaxe would not be given to the player, even though it was technically parented under the player’s backpack (I used a print(NewItem.Parent.Parent), it returns the player even though there is no pickaxe in the toolbar itself).
I fixed the bug by adding a RunService.Heartbeat:Wait() before calling GivePlayerItem (I heard Heartbeat was better than a regular wait(), can anyone confirm this?). Even this doesn’t completely fix the problem, since I will still spawn in with no Pickaxe every now and then.
My guess is that something isn’t loading in fast enough when the game starts.
Is there any other way to fix this bug? I would rather not use a "wait(1) " to fix this bug. Thank you!
Hello!
This truly is a weird bug, and certainly is connected to game not loading fully for player. Waiting like this is definitely not a good practice, at least not long term, because magical code is to be avoided. Part of the code you’ve provided seems alright, and I’ve never had a similar problem by following the same concept.
Could the bug have something to do with other parts of the code?
As far as other questions go, I don’t think you need to use WaitForChild() in the second section. Since ServerStorage is part of the server and it’s content (not replicated) is available right away, I never needed to wait for items to load. Different story with Player:WaitForChild(“Backpack”), although Player.Backpack has also always worked for me, probably because you are waiting for player to be added, and backpack is part of player.
RunService.Heartbeat:Wait() is a much more consistent option compared to wait(). wait() is part of Roblox 30Hz pipeline and not only does it sometimes not run reliably, but delays are not uncommon as well. Run rate is the same (30 times per second), as opposed to RunService.RenderStepped, which runs with the rate of 60 times per second.
I’ve read somewhere once that when character is created in workspace, everything from player’s backpack is removed. Finally, try using Player.CharacterAdded:Wait() before giving the item away.
-- Replace
RunService.Heartbeat:Wait()
-- with
local character = Player.Character or Player.CharacterAdded:Wait()
-- or perhaps move the former statement higher in function.
I hope this helps!
EDIT
In case you decide not to define a new variable for the sole purpose of waiting for character to load, you can write:
if (not Player.Character) then Player.CharacterAdded:Wait() end
1 Like
Thank you! I tried using CharacterAdded like you said, and it seems to be working!
I have to put it outside of the if-statement for it to work. Here’s the full function if your wondering:
local function LoadSavedPlayerData(Player)
local character = Player.CharacterAdded:Wait()
local PlayerID = Player.UserId
for loop = 1, 3, 1 do
local Works , SavedPlayerData = pcall(function()
return PlayerDataStore:GetAsync(PlayerID)
end)
if Works and SavedPlayerData ~= nil then
CurrentPlayerData[PlayerID] = GameDataAndScripts.CopyTables(SavedPlayerData)
CurrentRockAmount[PlayerID] = 0
local GoldAmount = CurrentPlayerData[PlayerID][1]
local BackpackType = CurrentPlayerData[PlayerID][2]
local PickaxeType = CurrentPlayerData[PlayerID][3]
PlayerLoadData:FireClient(Player , GoldAmount, BackpackType, PickaxeType)
GivePlayerItem(Player, PickaxeType)
break
end
if Works and SavedPlayerData == nil then
local Works , NewPlayerData = pcall(function()
PlayerDataStore:SetAsync(PlayerID , {StarterGold , StarterBackpack, StarterPickaxe})
end)
if not Works then
print("Failed to create data")
end
end
if not Works then
print ("Failed to load data")
end
end
end
Thank you for your help, I’ll mark this as the solution.
1 Like