Maybe try
script.Parent.Text = (game.Players.LocalPlayer.leaderstats.Coins.Value.. "$")
Instead of 3 dots, I’d use 2 dots. Would work the same.
script.Parent.Text = (game.Players.LocalPlayer.leaderstats.Coins.Value..“$”)
I did, it changed automatically to 3 dots lol
Oh, well.
@ArkolaTV Can you open the developer console and check if there are any errors? Might show us more insight of the problem.
Might want to check that the leaderstats folder exists first as well. If the local script runs before the leaderstats are created it will error.
It might be that because when i run it one time after publishing it it works but all the others run doesn’t show the value in the gui. How do i make this ?
@ArkolaTV
have you tried this?
(the problem happen beacuse that check when the coins value change to other value example: if the coins value is the same value so by the script that he made the coins no going to display on the ui until the coins value get change. but after the coins value get change so is display the coins amount on the ui. however he can also do that with “while wait() do” and then is going to display always.)
while wait() do
script.Parent.Text = game.Players.LocalPlayer.leaderstats.Coins.Value .."$"
end)
also he can stay use with the same code but with one change:
script.Parent.Text = game.Players.LocalPlayer.leaderstats.Coins.Value .."$"
game.Players.LocalPlayer.leaderstats.Coins.Changed:connect(function()
script.Parent.Text = game.Players.LocalPlayer.leaderstats.Coins.Value .."$"
end)
actually he can do that beacuse i am doing that with same way and this is works.
There’s no evidence of debugging or if the console is throwing anything so actually knowing what your problem is here is impossible. Please do some debugging here and make sure your Guis are set up properly, otherwise we can’t really discern any causes of error.
From the client’s end, use some variables to avoid redundancy and don’t let your code assume that instances exist. It would also be more preferable to have your LocalScript directly descend the PlayerGui rather than a nested element because it becomes worse off to work with.
In either case, assuming you’re still working with your current setup:
**Note: Changed this code sample. It now fires with initial state.
local LocalPlayer = game:GetService("Players").LocalPlayer
-- Because you don't parent Coins before leaderstats, Coins is not guaranteed to
-- be replicated with the folder, so now you have to unnecessarily use two waits.
local leaderstats = LocalPlayer:WaitForChild("leaderstats")
local coins = leaderstats:WaitForChild("Coins")
-- Create a function so we can avoid redundancy later
local function updateCurrencyUI(newValue)
script.Parent.Text = tostring(newValue) .. "$"
end
-- Changed on ValueObjects will fire with the new value, which will be
-- newValue in the function.
coins.Changed:Connect(updateCurrencyUI)
-- Run it for the first time so we can fire with initial state.
updateCurrencyUI()
From the server’s end, there are various improvements to be made.
There’s a thread you may or may not be aware of, to not use the parent argument of Instance.new. While you don’t do that here, you are still setting the properties of objects after parenting them, which still invites that performance loss. You ideally only want to parent when everything is set up.
With the way you’re using the pcall, you aren’t utilising the full benefits of it. A pcall is meant to run a function in protected mode and catch any errors thrown by it. It returns two values: whether the function successfully ran or not and any returned values. You should make good use of those values as if there is a problem (e.g. DataStore outage), not only can you handle that case but report on it as well so you’re actually aware there is a problem.
Continuing on with the above, if the pcall throws an error, it will return an error message. As you do not check for the success value, the code below will throw an error because you’ll be attempting to set the value of a ValueObject to a string when it is expecting a number. You need to handle that case. Just because they don’t return anything, doesn’t mean they’re new players.
Incorporating all this feedback together, here’s what you can expect your code to look like:
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local DataStore = DataStoreService:GetDataStore("TestDataStore")
local CURRENCY_NAME = "Coins"
-- It would be good to incorporate retrying as well, or a failure redundancy
-- method that calls UpdateAsync over SetAsync for failed saves.
local dataErrorFor = table.create(Players.MaxPlayers)
local function playerAdded(player)
local playerKey = CURRENCY_NAME .. player.UserId
local folder = Instance.new("Folder")
folder.Name = "leaderstats"
local currency = Instance.new("IntValue")
currency.Name = CURRENCY_NAME
local success, ret = pcall(function ()
return DataStore:GetAsync(playerKey)
end)
if success then
print("DataStore fetched successfully")
if ret then
print("Data found, setting to value")
currency.Value = ret
else
warn("No data in successful fetch, new data created")
currency.Value = 1000
end
else
warn("Unsuccessful fetch for userId=" .. player.UserId)
dataErrorFor[player.UserId] = true
currency.Value = 1000
end
currency.Parent = folder
folder.Parent = player
end
local function playerRemoving(player)
if not dataErrorFor[player.UserId] then
local playerKey = CURRENCY_NAME .. "-" .. player.UserId
local currency = player.leaderstats[CURRENCY_NAME]
DataStore:SetAsync(playerKey, currency.Value)
else
-- To avoid data loss and overwriting with false data, we do not save
-- for players who had a fetch error. Look to incorporating a
-- retry or rebounding system.
warn("Data not saved for userId=" .. player.UserId)
end
-- Ensure player key gets removed from our tracker table
dataErrorFor[player.UserId] = nil
end
-- Consider writing a saving function to call on all players instead, kicking
-- them doesn't guarantee PlayerRemoving will fire. I'll leave this unchanged.
local function onClose()
for _, player in ipairs(Players:GetPlayers()) do
player:Kick("Game update")
end
-- IIRC wait will not stall server closure because at this point, there are
-- no other scheduled tasks, meaning the server can now close.
wait(5)
end
Players.PlayerAdded:Connect(playerAdded)
Players.PlayerRemoving:Connect(playerRemoving)
game:BindToClose(onClose)
for _, player in ipairs(Players:GetPlayers()) do
playerAdded(player)
end
My fixes are independent of yours, I’m not quite sure what kind of response you’re looking for by raising yours to me. If you want me to review it though, I can: and it’s not a good fix. Your second one is though, but it could use some improvements.
Please don’t ever suggest to someone, without strong basis, that they should change from an event-driven system to loops. If there’s already an event provided to you to connect to in order to trigger an event, you shouldn’t use a loop. While wait is also bad practice.
The issue isn’t that the coins value is changing ahead of time. Changed internally will only fire after a property is set. For ValueObjects, their Changed event is specially designed to fire with the new value since their only special property is Value, the rest hailing from the root instance.
Having an initial state is probably the issue here, but again, I have a lot of other feedback than just this one LocalScript. That could very well be the problem though, but in that case you might want to use an actual function to avoid code redundancy, like so:
local LocalPlayer = game:GetService("Players").LocalPlayer
local leaderstats = LocalPlayer:WaitForChild("leaderstats")
local coins = leaderstats:WaitForChild("Coins")
local function updateCurrencyUI(newValue)
script.Parent.Text = tostring(newValue) .. "$"
end
coins.Changed:Connect(updateCurrencyUI)
updateCurrencyUI()
I don’t find what’s wrong, i’m gonna make again the whole script.
I’m not quite sure but when creating your leaderstats, you used an IntValue, which has a property named “Value”. When detecting the change, you should be detecting it in the value.
So, your code would look a bit like this:
game.Players.LocalPlayer.leaderstats.Coins.Value.Changed:connect(function()
script.Parent.Text = game.Players.LocalPlayer.leaderstats.Coins.Value .."$"
end)
Maybe make sure your text is visible (there is a Visible
property) and also make sure the textColor3
is not the same as the background color 3. Also, Z Index
is a property that determines the z index of a GUI object, so try increasing that to see if it is hidden behind the other GUI. There is also a text transparency property, make sure that is set to 1
I might be going insane but in between the Value and the “…” is there a space?
But try the something like this \ /
local player = game.Players.LocalPlayer
local cash = player:WaitForChild("leaderstats").Cash
local TextBox = script.Parent.TextBox
TextBox.Text = cash.Value..$
silver.Changed:Connect(function()
TextBox.Text = cash.Value.."$"
end)
What is “silver” ?
30characters
Oops. That is part of my currency, I forget to edit that to cash. Lol
So in order the leaderboard have to start before the cash value gui ? Am i correct ??
The leaderstats folder has to start first then the Values are added then the data store adds the data.
So using the
silver.Changed:Connect(function()
end)
It will update when the value turns from nil to whatever your data is.