GUI only tweens once

  1. What do you want to achieve?
    I was working on a shop. Before working on the actual buying script, I want to script the button to tween the frame to be visible first.

  2. What is the issue?
    The GUI only tweens when I step on the brick and close it for the first time. Subsequent attempts touching the brick does not tween the GUI even though it is printing the checks.

  3. What solutions have you tried so far?
    Nothing much. I tried removing the check to see if the GUI was already open or not to see if that was breaking the script but even after removing that it still would not tween. I also added in wait() to some parts to see if the script was too fast or something. I am honestly clueless. This script should be working. Besides it works fine the first time round. I have no idea why it would not work the subsequent tries.

Here is the script inside the shop brick thing:

local isOpen = false
script.Parent.Touched:Connect(function(hit)
	if hit.Parent:FindFirstChild("Humanoid") then
		local playerz = game.Players[hit.parent.Name]
		local gui = playerz.PlayerGui:FindFirstChild("Shop")
			if isOpen == false then
				wait(0.1)
				print("should be open")
				gui.Frame:TweenPosition(UDim2.new(0.5,0,0.5,0),"Out","Linear",0.3)
				wait(0.4)
			    isOpen = true
		end
	end
end)

game.ReplicatedStorage.UpdateSelected.OnServerEvent:Connect(function(player)
	isOpen = false
	print(isOpen)
end)

Here is the local script inside the shop GUI(just the exit button part)

local GUI = script.Parent.Parent:WaitForChild("Frame")

GUI.ExitButton.MouseButton1Click:Connect(function()
    GUI:TweenPosition(UDim2.new(0.5,0,2,0),"In","Linear",0.3)
    wait(0.3)
    game.ReplicatedStorage.UpdateSelected:FireServer()
end)

It might be really obvious or something I may have missed out or left old code since before I wanted it to change a bool value to check if it was open but I decided a local var inside the script would work just fine.

By looking at your scripts, it looks like you have the GUI opening on a server script and closing on a local script, I see you have 2 options to fix this:

Option 1:

Check whether the GUI is open manual on the server side, currently when it is closed your variable isOpen is not changed to false when it is closed and won’t without remote events. so you could change the code to check the position or even easier, add a boolean variable in and change that because both script would be able to see it and change it there.

Option 2:

Fire a remote event from the server to the client side when the brick is touched telling the client to open the GUI and do all the tweening from the server side and tracking whether or not the GUI is open.

1 Like

I chose the second option and well, it works.

Thanks, I guess i’m still slightly confused about local and client sides

You shouldn’t be worrying about about parts of your script running too fast. In your case using wait isn’t really needed. Here is a really good community resource about avoiding wait(): Avoiding wait() and why.

The server shouldn’t be handling this stuff because it is a waste of server resources. Instead the client should be checking when the brick is touched and opening the GUI them self without the server needing to verify it. Anything located on the client can be exploited so using the server to verify a GUI opening is pointless because an exploiter will be able to open it whenever they want anyway. An exploiter will be able to open the GUI even when they haven’t touched the part regardless of the server sided checks.

Involving the server in input tasks over complicates the issue in most cases because involving the server isn’t necessary. In most cases the client should be one that handles any input like GUI tweening and opening and closing GUI’s. The servers resources should saved for more critical things like data stores and server side verification.


The reason why your script is only working once is because you never set the isOpen variable back to false. This means each time you run the script after it has ran once it always thinks the GUI is open because the isOpen variable is never set back to false.

@Canopius bad idea , It is never recommended to handle UI related actions on the Server at all. You should always utilize Local scripts for that, which would lead to better latency (through separate local scripts for every player there would be much less visual lag then with one script handling UI for every player in the game) , and better user experience ultimately.

@FdPros in your case I would FireClients instead and then from a local script do the UI related stuff. Firing an event each time a player steps on a part (especially if the event is going to be fired constantly, and multiple players are going to touch it) is not as good as firing the clients , as (the better option is) demonstrated in this code sample :

A script in the part (a server script) :

  --// Variables, Dependencies
  
   local debounce = true
     local players = game:GetService("Players")

  local event = game.ReplicatedStorage.Event
  
  --// Function
  script.Parent.Touched:Connect(function(hit)
      local touchedPlayer = players:GetPlayerFromCharacter(hit.Parent)
      if touchedPlayer and debounce then
         debounce = false
           event:FireClient(touchedPlayer) --[[ do this for every player by using FireAllClients() instead
	  and removing the touchedPlayer instance while firing.                                                                                                                      ]] 
          --// FireAllClients a RemoteEvent, where you'll Connect OnClientEvent in the UI and update it
            wait(3) --// Cooldown, for debounce
          debounce = true
        end
      end)  

And a Local script in StarterPlayerScripts :

 --//Variables and Dependencies
 
  local Players = game:GetService("Players")
  local ReplicatedStorage = game:GetService("ReplicatedStorage") 

  local player = game.Players.LocalPlayer
  local event = ReplicatedStorage:WaitForChild("Event")

--// Function
  event.OnClientEvent:Connect(function()--for the touched player in the previous script
    local PlayerGui = player:WaitForChild("PlayerGui")
      print("gui found for"..player.Name)
         local guiFrame = PlayerGui.ScreenGui.Frame
           guiFrame.Visible = true
           print("tweening..")
         --Tween the gui/code here
         wait(1)
       guiFrame.Visible = false               
  
    end) 

That should work, it’s tested and in my opinion it’s a better option than from the two provided by @Canopius

That is the option that @Canopius mentioned so I dont know why it would be better?

Are you sure you’ve even read my post? I clearly offered a totally different solution.

Obvious Differences :

  • He did it on the server, while I fire clients instead of firing a separate event each time. In a way reducing visual lag as there are separate local scripts that would handle Ui each time a client is fired.

  • I implemented debounce without which in @Canopius’s case the event would fire a trillion times.

  • My code does not depend on one server script to handle all UI for every single player in the game hence improving latency.

  • My code does not fire an event each time the part is touched, instead the event is separately fired for one specific player .

aside from what @waterrunner has mentioned, in my previous post I also clearly explain why my proposed option is much more viable and a better solution compared to the one provided by Canopius

I think you should read his second option again. He did not do it on the server he did what you did and fired a remote to tell the client to open the frame.

I don’t think that’s what he said,
In both options what I see is “do the tweening from the server side” through one phrase or the other, whereas it is not recommended to do so.

Its the same concept its not a whole different solution.

Firing a client and still handling the UI on the server is a waste of game resources, when you fire the client you should ‘take advantage’ of that and handle all UI on the client (tweening etc. ) . It’s a totally different idea from firing an event for a specified player .

Yes, I agree it is a bad idea to do any UI on the server however I suggested it as it was closest to @FdPros original code. The best option has already been mentioned by @waterrunner by doing everything client sided.

2 Likes

cc: @XxELECTROFUSIONxX
cc: @MineDevs
cc: @Canopius

Both of the solutions described in this thread are adequate solutions because they both fix the problem and work. However there are sometimes better solutions to the issue that may work better or are more performance friendly. It is alright to disagree with people providing you provide a constructive response to why you disagree to the point being said.

Handling UI on the server isn’t recommended because in most cases there is no point in doing so. You aren’t exactly securing your UI from being exploited because the UI is on the client meaning that they have full control over it. They can modify it and change it regardless of what security checks you have in place on the server. Another problem with handling UI on the server is that it makes all your UI scripting more complicated than it needs to be.

If you set up your client and server correctly then if an exploiter does exploit their UI it would be pointless because they wont gain anything. This is because all the important parts of your game will be ran from the server and you will have the proper server sided checks in place when necessary.

With all that said, there are some cases where you need to heavily involve the server but not let the server directly control the UI. A case where you would need to heavily involve the server is when you are making lets say a trading system. You would have to constantly do server sided checks and multiple data store calls to a make the whole system work. Ultimately the client should be the one that does stuff to their UI like visual changes.

I could go on forever about this stuff so I am not going to say anymore because it is starting to get off-topic. In short the server shouldn’t ever be directly controlling the clients UI. Instead the server should act as a place where things are verified and all the important stuff is handled like stat changes. It is also better to handle anything regarding input on the client and have the server verify it when necessary.

1 Like

Just to add on, if you would like to have some security to prevent people enabling the GUI and purchasing items away from the shop (which may have been the original reason for it being server sided), check the distance of the player from the shop when they try to buy something - magnitude is possibly your best option - on the server side to ensure they are not too far away.

1 Like