local formatNumber = require(game:GetService("ReplicatedStorage"):FindFirstChild("FormatNumber"))
local function billboardRemoval(character)
local head = character:FindFirstChild("Head")
if head then
local billboardGui = head:FindFirstChild("PlayerBillboardGui")
if billboardGui then
billboardGui:Destroy()
end
end
end
local function updateBillboardValues(billboard, cash, multi, rebirth)
if billboard then
if cash then
billboard.Cash.Text = "Cash: "..formatNumber(cash.Value, formatNumber.FormatType.Suffix)
elseif multi then
billboard.Multi.Text = "Multi: "..formatNumber(multi.Value, formatNumber.FormatType.Suffix)
else
billboard.Rebirth.Text = "Rebirth: "..formatNumber(rebirth.Value, formatNumber.FormatType.Suffix)
end
end
end
game:GetService("Players").PlayerAdded:Connect(function(player)
player.CharacterAdded:Connect(function(character)
if character and player.CharacterAppearanceLoaded:Wait() then
local leaderstats = player:WaitForChild("leaderstats")
local playerstats = player:WaitForChild("Playerstats")
if leaderstats and playerstats then
local cash = leaderstats:WaitForChild("Cash")
local multi = playerstats:WaitForChild("Multi")
local rebirth = playerstats:WaitForChild("Rebirth")
if cash and multi and rebirth then
local humanoid = character:WaitForChild("Humanoid")
local head = character:WaitForChild("Head")
if humanoid and head then
local replicatedStorage = game:GetService("ReplicatedStorage")
local playerBillboardGui = replicatedStorage:FindFirstChild("PlayerBillboardGui")
if playerBillboardGui then
local billboard = playerBillboardGui:Clone()
billboard.Parent = head
if billboard then
billboard.Cash.Text = "Cash: "..formatNumber(cash.Value, formatNumber.FormatType.Suffix)
billboard.Multi.Text = "Multi: "..formatNumber(multi.Value, formatNumber.FormatType.Suffix)
billboard.Rebirth.Text = "Rebirth: "..formatNumber(rebirth.Value, formatNumber.FormatType.Suffix)
task.wait()-- Give a short interval before refreshing billboard
updateBillboardValues(billboard, cash, multi, rebirth)
cash.Changed:Connect(function(Value)
updateBillboardValues(billboard, cash, multi, rebirth)
end)
multi.Changed:Connect(function(Value)
updateBillboardValues(billboard, cash, multi, rebirth)
end)
rebirth.Changed:Connect(function(Value)
updateBillboardValues(billboard, cash, multi, rebirth)
end)
end
-- Clean up the billboard when the humanoid dies
humanoid.Died:Connect(function()
billboardRemoval(character)
end)
end
end
end
end
end
end)
end)
I apologize if the codes a bit of a mess I was moving sections around to see if I could find a solution.
I’ve ran into similar problems like this before. Essentially, since you have changed events connected to different leaderstats values that are constant and aren’t disconnected, when the leaderstats are updated, it will run both the new event connections, and the old ones.
tl;dr: It’s a memory leak, your code is trying to access old references because they aren’t properly cleaned up after the player dies.
The easiest way I can tell you to fix the problem is by disconnecting the event connections when the player dies and respawns:
-- Example
local eventConnections = {} -- this table holds all the currently connected event connections
table.insert(eventConnections, cash.Changed:Connect(function()
---...
end)) -- this adds the RBXScriptConnection to the eventConnections list
-- listen to when the player dies
humanoid.Died:Connect(function()
for _, connection in eventConnections do
connection:Disconnect() -- disconnect the connection so it doesn't run in the future
end
end)
I was actually thinking about the cash problem (since it’s the only one at the moment causing the issue) and I believe it’s because I have a while loop running in the playerData script.
Yes, but I’m glad you told me about the while loop. Over time with the creation of new player characters (respawning), there will be new while loop creations and the amount of money the player gets per WAIT_TIME will also increase.
To fix this is quite simple:
local playerIsAlive = true
-- inside the humanoid Died event, turn the boolean off
humanoid.Died:Connect(function()
playerIsAlive = false
---...
end)
-- this will only run while the player is alive, preventing old or duplicate loops from being created
while playerIsAlive do
task.wait(WAIT_TIME)
---...
end
I should probably move the while loop to the billboard so it only runs while the billboard exists and player is alive (as you’ve stated). There really isn’t any reason to check for deaths anyway since no one will die in the game but I figured players will try anything so I’d better address it. The update problem still exists.
My guess is that because the cash.Changed event is still active, even after destroying the billboard, the cash.Changed event fires to attempt to update the cash text label. But since the player died and the billboardGui object no longer exists, but the reference to the billboardgui still exists within the billboard variable, there aren’t any children that truly exist in the billboard gui.
You can add a check to make sure the billboard gui still has a parent. I would add this to the updateBillboardValues() function.
local function updateBillboardValues(billboard, cash, multi, rebirth)
if billboard then
if billboard.Parent then -- Will make sure the billboard exists
-- everything else here
end
end
end
If you can figure out any other way of verifying that the billboard variable contains a still-existing object would work.
Thank you for the Parent check it worked well. The billboard updated the values. I think I know why the Multi isn’t updating though it’s probably because the while loop is hogging the function call even when the multi changes the cash is already been called. Should I use a coroutine for this or something (I’ve never done that before) – Is this a correct assertion?
Great to know it worked
I thought the while loop was in a separate script? Yes, a coroutine for the while loop would allow the script to listen for event calls while simultaneously running the while loop.
I also created a new function for cash and made the coroutine for the while loop. Everything works as intended. Thanks to all that helped me understand all this. I had to choose a comment as solution but everyone here helped.