GUI not updating for server

I am trying to create a script that updates the GUI on a player accessory when the leaderstats value changes. I am currently updating the values locally and on a server script but the GUI isn’t updating on the server what would be the best approach to solve this issue?

Local Script:

while wait() do
	local player = game.Players.LocalPlayer
	game.ReplicatedStorage.Remotes.BackpackValue:FireServer()
	script.Parent.Text = player:WaitForChild("leaderstats"):FindFirstChild("Oil").value.. "/20"
end

Server Script:

game.ReplicatedStorage.Remotes.BackpackValue.OnServerEvent:Connect(function()
	game:GetService("Players").PlayerAdded:Connect(function(client)
		client.CharacterAdded:Connect(function(character)
			local player = game.Players.LocalPlayer
			character.Backpack.Handle.GPart.SurfaceGui.TextLabel.Text = player:WaitForChild("leaderstats"):FindFirstChild("Oil").value.. "/20"
		end)
	end)	
end)

The way you did it wont work since it’s going to make a PlayerAdded event every tick or so, which is not optimal

What I would is in the code you have to make the leaderstats values, use the Changed event on the Oil so when the Oil value changes, it’ll update the Text on the textlabel

There is multiple issues with your script,

  1. The backpack is parented to the player not the character
  2. LocalPlayer can only be called from the client
  3. Why are you updating a gui thats inside of a tool?
  4. Use Value.Changed, instead of an infinite loop, and don’t fire to the server that many times
  5. Why do you change the gui value twice?

To fix this,

  1. instead of character.Backpack, do player.Backpack
  2. In the remote, add the player parameter (remote.OnServerEvent:Connect(function(player)
  3. Parent that gui to the players PlayerGui (player.PlayerGui), and edit it there
  4. Use .Changed
  5. Change it once, on the client

Here are the edited scripts (may need to mess with them didnt test)

--LocalScript
local Oil = game.Players.LocalPlayer.leaderstats.Oil

Oil.Value.Changed:Connect(function()
    game.ReplicatedStorage.Remotes.BackpackValue:FireServer()
    script.Parent.Text = Oil.Value.. "/20"
end)

--ServerScript not needed

Edit: I didn’t see the attached pictures and I said to not change it on the server since I thought it was a gui. I’m assuming that this is parented to the workspace, so the LocalScript is not running, since it can not run in the workspace. You can easily do the same thing with a serverscript only

--Assuming this is parented to the players character

local player = game.Players:GetPlayerFromCharacter(script.Parent.Parent.Parent.Parent) --Assuming its Script > TextLabel > SurfaceGui > Backpack > Character

player.leaderstats.Oil.Changed:Connect(function()
     script.Parent.Text = player.leaderstats.Oil.Value.. "/20
end)
2 Likes

What EmbatTheHybrid is true, and to add to that, you shouldn’t be using remote events, which burden the server in this case with rapid signals, and are not necessary, because you only need to do changes on the server. As you probably already know, such changes to GUIs on the client do not replicate. You can also narrow listening for value changes down to only values using :GetPropertyChangedSignal() method.

@Fl_ank
Something like this would be the final result:

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

Players.PlayerAdded:Connect(function(player)
	-- After leaderboard is created and player has the copy.
	local oil = player.leaderstats.Oil
	local _connection
	player.CharacterAdded:Connect(function(character)
		local label = -- Proper TextLabel path here.
		
		if (_connection) then _connection:Disconnect() end
		_connection = oil.Changed:Connect(function(value)
			label.Text = oil.Value .. "/20"
		end)
	end)
end)
What not to do
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

Players.PlayerAdded:Connect(function(player)
	-- After leaderboard is created and player has the copy.
	local oil = player.leaderstats.Oil
	player.CharacterAdded:Connect(function(character)
		local label = -- Proper TextLabel location here.
		oil:GetPropertyChangedSignal("Value"):Connect(function()
			label.Text = oil.Value .. "/20"
		end)
	end)
end)

EDIT MemezyDev I think Backpack is a folder or some instance that holds value in workspace, not player.Backpack. Everything else seems correct, except such changes done by client won’t replicate to anyone else’s machine.

2 Likes

That would be correct, but you don’t really need to narrow the listening via GetPropertyChangedSignal as the Changed event for BaseValues, such as int values, only listen for when the Value Property changes, the only difference being .Changed will return the new value for usage.

And something unrelated since I’m not too experienced on Events, but wouldn’t it make the event for checking the Oil’s Value again when the character respawns, wouldn’t that make more than one event for that or does it overwrite the event? I think it would also be good to disconnect the event on death to ensure only one event for checking the value is present at a time. Although I’m unsure about that

1 Like

Didn’t see the attachments, thought he wanted the actual backpack. I was editing when you edited your post lol

1 Like

EDIT (Added a couple of words to correct some information in case anyone ever read this.)


.Changed events listens for any changes made to particular instance. IntValue has 6 active properties and some deprecated ones, which all fire when we make a change to one of them.

What I previously said is incorrect, because .Changed and :GetPropertyChangedSignal() have the same functionality here. Even though IntValue has a lot of properties and some hidden and deprecated ones, .Changed event fires each time value changes. :GetPropertyChangedSignal() is a good practice when it comes to more complex instances, like humanoid, seat, and so on.

“Connections disconnect eventually when player respawns.” – Only partially true.

That stands if the code is part of a local script.

Local script example:

Local script connections disconnect eventually when player respawns. Disconnecting earlier only frees up memory quicker, and requires connecting humanoid.Died event, which is another connection and makes manual disconnection relatively questionable.

Server script example:

Since server script doesn’t stop executing when character is removed from game, the old connection remains active and doesn’t collect. Thanks to @EmbatTheHybrid for pointing that out, I forgot we are talking about server script, so the previous information is not true when we are talking about the server side.

I’m appending later post here with most likely valid information, at least according to my previous experience and tests.

Thanks to @EmbatTheHybrid again for bringing that up.

2 Likes

That is true, but that doesn’t apply to BaseValues, Changed only fires if their Value property has been changed, so if you changed their name, it wont detect that, but if you change their value, it will. To take fro mthe Article for Changed for IntValues for example,

IntValue.Changed

Your method and Changed would be the same, but Changed would return the new value, but would only apply to BaseValues and nothing else, so using GetPropertyChangedSignal would be the more general approach to use, but personally I would use Changed since I would need to use the new value, but of course to each their own.

Wow you made that edit by the time I was writing this haha

So if I understand correctly, eventually the old event for the Oil would be disconnected by itself by the time you connect it? I never knew that before, I thought it just keep piling up connections, hence why I suggested manual disconnection to help free up some memory, even if it’s making another connection, which would be disconnected anyways when the Character respawns

2 Likes

Server Script:

game.ReplicatedStorage.Remotes.BackpackValue.OnServerEvent:Connect(function()
	game:GetService("Players").PlayerAdded:Connect(function(client)
		client.CharacterAdded:Connect(function(character)
			local player = game.Players.LocalPlayer
			character.Backpack.Handle.GPart.SurfaceGui.TextLabel.Text = player:WaitForChild("leaderstats"):FindFirstChild("Oil").value.. "/20"
		end)
	end)	
end)

La funzione game.Players.LocalPlayer può essere usata solo nei LocalScript.

1 Like

I’m sorry for not clarifying the information correctly and stating some wrong information.

What I said stands, but only when the code is inside local script. Once new character is spawned, the old one stays present in memory for a relatively short time period and is collected by GC (garbage collector) soon unless it’s strongly referenced. Server script doesn’t stop working when player “dies” of course, so connection remains active.

Instead of connecting humanoid.Died, a better alternative would be storing current connection in a variable and disconnect it efficiently.

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

Players.PlayerAdded:Connect(function(player)
	-- After leaderboard is created and player has the copy.
	local oil = player.leaderstats.Oil
	local _connection
	player.CharacterAdded:Connect(function(character)
		local label = -- Proper TextLabel path here.
		
		if (_connection) then _connection:Disconnect() end
		_connection = oil.Changed:Connect(function(value)
			label.Text = oil.Value .. "/20"
		end)
	end)
end)

Connecting humanoid.Died would improve the situation, but add up some unnecessary code.

Thank you for bringing this up and please excuse me again for telling some partially false information today, I haven’t slept enough for a week now. :smile:

2 Likes

Okay I see now, thanks for clearing it up for me. Also I think my brain must’ve completely forgotten that @OP could just do that instead of putting it in a variable and disconnecting it when the player dies, that would be much more effective as an if statement is less demanding than an event. Thank you for clearing that up for me! and helping out my brain during a brain fart remember disconnection via if statement haha

2 Likes

This worked perfectly basically the main error was that I was using a local script inside of the workspace while it should’ve been a server script. Thank you all for your help and guidance!

2 Likes