2
votes

Changing UI_ELEMENT.Visible to true, and then false shows and hides the UI element, however when I switch it to true again it doesn't reappear. I believe this may be an issue of how I'm doing it rather than what I'm doing.

Hi, I'm new to Roblox Lua (But I have Javascript and C# experience). I am working on making a 'Garage' or 'Parts' GUI. I'm am trying to make a click detector on a text object set the UI_ELEMENT.Visible of a UI element to true. And a text button (Part of the previously mentions UI element) set that UI_ELEMENT.Visible back to false.

This process works fine until I run through it multiple times (e.g setting to true, then false, and then true again). The UI_ELEMENT.Visible is 'locked' at true (as in setting it to false just results in it being set back to true next frame) but the UI doesn't show.

Code:

click_detector1.MouseClick:connect(function(player) -- When clicked

  
    _G.PlayerInfo[player.Name].status = "In Garage" -- set player status to in garage (works fine no issues)
    
    _G.PlayerInfo[player.Name].topbar = "" -- reset topbar (works)

    
    print("this is only supposed to happen once") -- a check to see if this is running more than once

    
    game.Players[tostring(player.Name)].PlayerGui.Garage.menu.Visible = true -- one way that should work

    --.Enabled = true -- another way that should work

    --.menu.Position = UDim2.new(0.5, 0, 0,0) -- another way that should work (setting position to center of screen)

end)

The above is in a server script (let's call it script #1).

button = script.Parent

local function onButtonActivated()
    
    local Players = game:GetService("Players")
    
    local player = Players.LocalPlayer -- get the local player
    
    print("I am only running once") -- test to see if this is running more than once
    
    game.Players[tostring(player.Name)].PlayerGui.Garage.menu.Visible = false -- one way that should work

    --.Enabled = false -- another way that should work

    --.menu.Position = UDim2.new(10, 0, 0,0) -- another way that should work (change x scale to off screen)
    
end
 
button.Activated:Connect(onButtonActivated)

The above is in a local script (let's call this script #2).

The interesting thing is that none of the methods I proposed in the 'another way that should work' actually function more than the initial first cycle of the loop (e.g setting to true, then false, and then true again).

Also logging the tests to see if they run multiple times only runs once each time it is cycled through (Like it should). However, this means the code for setting it to visible is also running, but not logging an error or doing what it should do.

Thanks, Daniel Morgan

1
If I understand your question properly, are you asking why this code starts to fail after turning it on/off a few times?Kylaaa
@Kylaaa Yes, that is what I don't understand.Daniel Morgan

1 Answers

0
votes

I believe the issue lies with your use of a server script and local script. LocalScripts only change what's on the player's client. Non-local scripts change whats on the server. In other words, non-local scripts affect everyone while LocalScripts only affect individual players.

Setting the visibility of the GUI to false through a LocalScript will only change the GUI on the player's client. However, the server will still see the player's GUI visibility as true. This discrepancy may be causing you issues.

I would suggest an alternative method using RemoteEvents. Instead of changing the GUI visibility to false in a LocalScript as you do in script #2, I would use a RemoteEvent to do that instead. In your case it would look something like the following:

The following is what would be in a non-local script:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
 
local remoteEvent = Instance.new("RemoteEvent",ReplicatedStorage)
remoteEvent.Name = "MyRemoteEventName"
 
-- player is the player object, visibility is a boolean (true or false)
local function ChangeGuiVisibility(player, visibility)
    player.PlayerGui.Garage.menu.Visible = visibility
end
 
-- Call "onCreatePart()" when the client fires the remote event
remoteEvent.OnServerEvent:Connect(onCreatePart)

You can Fire this remote event from a local script like this:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local visiblity = false
local remoteEvent = ReplicatedStorage:WaitForChild("MyRemoteEventName")
 
-- Fire the remote event. 
remoteEvent:FireServer(visibility)-- NOTE: the player object is automatically passed in as the first argument to FireServer()

Here is a very good guide on RemoteEvents: https://developer.roblox.com/en-us/articles/Remote-Functions-and-Events

Basically, RemoteEvents allow you to bridge the gap between the client and server. The client can fire an event to which the server will respond to. A while ago, this was not the case with Roblox. Changes from the client were visible to the server, which made exploiting games very easy.

Also, I'd like to suggest some changes to your first script, which may be helpful for you in the future. Instead of:

game.Players[tostring(player.Name)].PlayerGui.Garage.menu.Visible = true

try

 if player.PlayerGui:FindFirstChild("Garage") then
    player.PlayerGui.Garage.menu.Visible = true
 end

There is no need to access game.Players since the MouseClick event already returns the player object that clicked the button. I use FindFirstChild which checks if the Garage GUI exists. This can prevent potential errors from occurring and is often good practice.

Hopefully this helps, please follow up if you're still having issues.