Anyway to make a ui change serversided

this probably sounds stupid, but is there anyway to make the ui change serversided. for example,

script.Parent.Text = 'hi'
wait(10)
script.Parent.Text = 'bye'

if a player joined 20 seconds after the first player, they would see ‘bye’, and not ‘hi’.

this is probably easily fixed, and i’ve just been too tired to work it out in my head
thanks,

1 Like

By definition, UI objects are client sided. They are never on the server. (I have been told this is false, but this still stands.)

However, you can use RemoteEvents and RemoteFunctions to send a message from the server to clients to achieve your desired result.

function change(text)
local guiName = "the name of the gui. this assumes you are finding just a text box"
 for i,v in pairs(game.Players:GetPlayers()) do
  local path = v.PlayerGui[guiName]
  local frame = path.Frame
  local textBox = frame.TextBox
  textBox.Text = tostring(text)
 end
end
wait(10)
change("bye")

something like this

EDIT: i did some stupid stuff

I’m pretty sure you can get UI items in each players PlayerGui on the server

PlayerInstance.PlayerGui.ScreenGui.Text = "Text";

Still a bad idea to do so, as the client should be handling it and not the server. Even if you could, which I have tested on studio and it seems that you could in theory, it’s not a good idea to do so as you would be essentially giving something that the client manipulates to the server. Just a waste of memory on the server.

for example, im trying to recreate the class schedule ui on this game [Read Description] Little Dreamies Daycare - Roblox

like if the 3rd player joins 1 minute after the fist and second, they will see all the same ui text, even if it changed 20s before they joined, its hard to explain

the fact that since im firing the remotevent from the server, it needs a

game.Players.PlayerAdded:Connect(function()

to run it, which will just mess up the wait().

I’d imagine that you would want a server script to be calculating the text displayed.

In a server script:

local remote = path.To.Remote -- you get the idea
local data = "This is the text sent to the client"

remote.OnServerEvent:Connect(function(plr)
    remote:FireClient(plr, data) -- It's not a good idea to use RemoteFunctions.
end)

-- Scripts that change the data, etc.

data = "new data"
remote:FireAllClients(data)

And then on the client:

local remote = path.To.Remote

local data = ""

local function handleChange()
    -- change a gui object?
end)

remote.OnClientEvent:Connect(function(newData)
    data = newData
    handleChange()
end)
remote:FireServer()

This is just a simple example, but it should help you out.

I would use two RemoteEvent’s in this case. One for hi and one for bye. You could instead use a RemoteFunction but that would be more complex.

RemoteEvent: RemoteEvent | Documentation - Roblox Creator Hub
RemoteFunction: RemoteFunction | Documentation - Roblox Creator Hub

I don’t imagine that you would have to do any of that, considering FireAllClients can be used.

didnt work

--server script--
local data = 'class1'
local data2 = 'class2'

game.ReplicatedStorage.ChangeClass.OnServerEvent:Connect(function(plr)
	game.ReplicatedStorage.ChangeClassB:FireAllClients(plr, data)
	wait(20)
	game.ReplicatedStorage.ChangeClassC:FireAllClients(plr, data2)
end)
--local script--
game.ReplicatedStorage.ChangeClassB.OnClientEvent:Connect(function(plr, data)
	script.Parent.Text = data
end)

game.ReplicatedStorage.ChangeClassC.OnClientEvent:Connect(function(plr, data2)
	script.Parent.Text = data2
end)

The reason I put an OnServerEvent connection in my original script was so that when a player joined, they could get the info without waiting for the value to change.

This script will not run because it does not send any values to either side.

On the server, without connecting to the OnServerEvent connection, you would fire all clients when the value changed. That’s what FireAllClients should be used for.

As for the client whenever it joined, you would need to request the data from the server because the server has not sent anything to that client, and it would not until the value was changed.

Also you only need one remote if you’re doing this method.

the script does fire, and i understand what your saying, but i feel you are over complicating this, how would i run the fireallclients when the server starts, and not when players join.

Yeah I can understand how this appears as overcomplicating it.

If you’re still confused, this resouce will probably help you.

In your use case, controlling the UI from the server may benefit you, so I can’t really say that it’s a horrible idea anymore.

Here’s an example using another method if you’re all about simplicity.

local function changeAllClients(textToChangeTo)
    for _,v in pairs(game:GetService("Players"):GetChildren() do
        v:WaitForChild("PlayerGui"):WaitForChild("ScreenGui"):WaitForChild("TextLabel").Text = textToChangeTo
    end
end

Sorry if this appeared as dismissive towards other options, but I wouldn’t do this method too much unless you are absolutely sure that the client won’t screw up.

EDIT: I’m going to back away and let other people solve this if this doesn’t solve it.

Changing this from the client is extremely inconvenient.
If you know what your doing, you’d know that you can access guis from the server and not have to waste remotes on it.

Heres what your probably looking for:

local GuiName = "Schedule"
local LabelName = "Class"
function UpdateSchedule(TextToChangeTo)
   for _, v in pairs(game.Players:GetChildren()) do
      if v.PlayerGui:FindFirstChild(GuiName) then
         v.PlayerGui[GuiName][LabelName].Text = TextToChangeTo
      end
   end
end

You might have to change the two first variables. Also, make sure you put the label that shows what class is starting into the base of the gui. :v

To use it, use

UpdateSchedule('class name or whatever')

and obviously you have to make it show for the players who are just joining or they wont see it change until the next class starts / the script updates everybody else.

game.Players.PlayerAdded:Connect(function(player)
   wait(1.5)
   UpdateSchedule(game.Players:GetChildren()[1][GuiName][LabelName].Text) -- idk how to get it a different way, you can change it if you assign a global variable.
end)

i’d recommend putting this last part at the bottom of the script so it doesnt pause the whole thread when a player joins.

The third code example makes no sense.

game.Players.PlayerAdded:Connect(function(player)
    wait(1.5)
    UpdateSchedule(game.Players:GetChildren()[1][GuiName][LabelName].Text) -- idk how to get it a different way, you can change it if you assign a global variable.
end)

This code example is explicitly changing all the guis for every single player.

You should probably revise it to something like this.

game.Players.PlayerAdded:Connect(function(player)
    player:WaitForChild("PlayerGui"):WaitForChild(GuiName):WaitForChild(LabelName).Text = currentText
end)

where currentText is the last known text that the server set. Shouldn’t be too hard to figure it out from there.

That was just using the function to update all. It shouldn’t change it for others since it should be the same but your code might make more sense to newer scripters i guess :v