GUI changes with script, but output doesn't show on screen

Trying to make a simple part counter using OnTouch but the GUI doesn’t update onscreen.
I know there is a simple answer but I’m new to GUIs. This LocalScript is in a Part in a tube that the “rocks” pass through. I tried printing to the Output window first and it counts just fine. The TextLabel.Text will update if I click on it when I play it in Studio but the screen still says “0 rocks processed”. Tried publishing the game and playing it but still no joy.

Someone’s going to point out my error and I’ll feel like an idiot, but that’s how I’ve learned most this stuff except for programming in BASIC back in the late 80’s!
I did a lot of tutorial searching and google searches and got many answers that were still linked to the forums (RIP) but nothing that states how a GUI’s display updates. I also tried free model GUIs as well but nothing really helped me there.

local x=0
text = game.StarterGui.processed.TextLabel
text.Text = x…" rocks processed"

brick = script.Parent

brick.Touched:connect(function(part)
x=x+1
text.Text = x … (x == 1 and " rock" or " rocks") … " processed"
end)

Instead of changing the text in StarterGui, change the text in PlayerGui.

2 Likes

Here are the next few issues you are going to run into

  1. Accidentally firing touched event without humanoid touching it
  2. Differentiating between different players that touched it
  3. Running a separate version of this script in every single rock(Assuming there are a lot of rocks) is highly inefficient

So here is how I would do it…

  1. Gather every rock into a single model. Then have a loop that can access all of the rocks
for _,v in ipairs (game.Workspace:WaitForChild("Rocks"):GetChildren())
if v:IsA("BasePart") then
v.Touched:connect(function(HitPart)
---Code Here
end)
end
end
  1. So now we gotta worry about making sure that its actually a player and not some random part touching it. To check most people just make there that there is a humanoid. To do that the :FindFirstChild() method because it can return nil if the object dosent exist without causing an error
v.Touched:connect(function(HitPart)
if v.Parent then
if v.Parent:FindFirstChild("Humanoid") then
--oof
end
end
end)
  1. Now you gotta figure out which player actually touched it so you can modify their gui ad not the starter gui from before. There is a handy little method in the Players Service called :GetPlayerFromCharacter which is self explanatory in the title
if v.Parent:FindFirstChild("Humanoid") then
local Player = game.Players:GetPlayerFromCharacter(v.Parent)
end
  1. And now we are back to where we started without a way to modify the players gui. So you could do Player.PlayerGui.processed.TextLabel.Text = "Whatever you want here" but most people would choose to relay the information through remote events because it is easier if you understand how they work.

Yeah, like Zeumus said, you’re changing the text in StarterGui rather than PlayerGui; this will cause the default Gui to change and any player that joins after will have their Gui say something else (if experimental mode is enabled)

2 Likes

“This LocalScript is in a Part in a tube that the “rocks” pass through. I tried printing to the Output window first and it counts just fine.”

Ah, k. I’m just starting to figure out this process so what I wanted was to make sure it was working. I’m planning on putting a Part with Collision Filtering in it around the ‘counter’ Part with the script in it to only allow Rocks to pass through the tube, keeping the Player from getting anywhere near the ‘counter’.

It’s going to be a single player game too. Too much lag with multi-Part bulldozer tracks moving with more than 1 player.

What @VineyardVine said is exactly what you should be doing. I only gave you a solution to what you were looking for but there were other problems which @VineyardVine gave you solutions to.

To extend on what @VineyardVine said: if you’re using a script, the PlayerGui’s contents are not visible to the server (unless you parent the guis to the PlayerGui from the server) so it might be better to do it in a LocalScript. Place that LocalScript under in StarterGui under your gui. Please remember that StarterGui is replicated (on player joined server or if ResetOnSpawn property is enabled for that ScreenGui- only that ScreenGui will replicate to the PlayerGui whenever a player respawns if that property is enabled) to the PlayerGui inside the player. Whenever you change a text in PlayerGui, that change is noticed. However it is not noticeable if you change it in StarterGui.

You can do a Touched event in the LocalScript. If you’re only displaying something then it doesn’t matter if you’re doing it in a Script or LocalScript as it isn’t a security concern. You should be doing displays in LocalScripts though. Although, you could on the other hand have it in a Script but you’ll need to fire a RemoteEvent to the client for that text to display (unless you parented the guis to the PlayerGui from the server which you could then change the text in a Script as it’ll be visible to the server)

LocalScript is in StarterGui.processed.TextLabel (player.PlayerGui.processed.TextLabel)

local part = workspace.Part -- the location of the "part" in workspace
local localPlayer = game.Players.LocalPlayer 

part.Touched:connect(function(hit) -- hit being what touched the "part" so a part or whatever
    if hit.Parent:FindFirstChild("Humanoid") then -- making sure the thing that touched the "part" has a Humanoid (e.g player, npc or whatever)
       local player = game.Players:GetPlayerFromCharacter(hit.Parent) -- getting the player from its character. If not a player in the server, it’ll be nil. For example if its a npc or something that isn’t a player in the server 
       if player then -- making sure the thing that touched the "part" is a legit player in the server so not a npc or something that has a Humanoid
          if player == localPlayer then -- making sure the player is the LocalPlayer (you) that touched the "part"
              script.Parent.Text = "You have touched the part" -- changed localPlayer.PlayerGui.processed.TextLabel text property to "You have touched the part" which will be visible to the LocalPlayer (you)
          end
       end
    end
end)

I’m on mobile so it’s hard to write code lol but thats a basic example of a Touched event (in a LocalScript).

If you have more than one part then here’s an example of that:

LocalScript is in StarterGui.processed.TextLabel (player.PlayerGui.processed.TextLabel)

local parts = workspace.Parts -- the location of the parts in workspace (in a Model or whatever)
local localPlayer = game.Players.LocalPlayer 

for _,part in pairs(parts:GetChildren()) -- going through each instance in workspace.Parts
  if part:IsA("BasePart") then -- making sure it is a part and not a Script, Model or whatever
    part.Touched:connect(function(hit) -- hit being what touched the "part" so a part or whatever
      if hit.Parent:FindFirstChild("Humanoid") then -- making sure the thing that touched the "part" has a Humanoid (e.g player, npc or whatever)
         local player = game.Players:GetPlayerFromCharacter(hit.Parent) -- getting the player from its character. If not a player in the server, it’ll be nil. For example if its a npc or something that isn’t a player in the server 
         if player then -- making sure the thing that touched the "part" is a legit player in the server so not a npc or something that has a Humanoid
            if player == localPlayer then -- making sure the player is the LocalPlayer (you) that touched the "part"
                script.Parent.Text = "You have touched a part" -- changed localPlayer.PlayerGui.processed.TextLabel text property to "You have touched a part" which will be visible to the LocalPlayer (you)
            end
         end
      end
    end)
  end
end

Remember, only use a LocalScript if you’re displaying but if you’re using it as a value then it’s secure to handle that server-side. If you’re doing it server-sided then you must know that the Touched event can be spoofed so it’s a good idea to have a if statement in that Touched event to check the magnitude from the player to the part to see if they’re really close.

Sorry if I seem a bit repetitive here, but I’m not trying to add a value when my character touches a rock, I’m trying to count when a rock passes through another Part.
A rock counter if you will.

Players won’t ever come into contact with the counter Part so I don’t need any mention of a Humanoid. There are no other loose Parts in the game that will contact the counter so a simple Touched function will suffice.

Basically all I had to do was place this script in the TextLabel of the StarterGui. Hehe I knew I was making it more difficult than it had to be.

local x=0
text = script.Parent
text.Text = x…" rocks processed"
counter = game.Workspace.TopChute.Counter

counter.Touched:connect(function(part)
x=x+1
text.Text = (x … (x == 1 and " rock" or " rocks") … " processed")
end)

Thanks for your help anyway!

1 Like