I have fixed this but I need to know where the scripts go that Kiriot22 fixed to work with FE.
There are multiple problems in your script
You use the method :findFirstChild()
. This is deprecated, or not recommended to use. To change this is by changing your deprecated method to :FindFirstChild()
Speaking of :FindFirstChild()
. You should use the method :WaitForChild()
. WaitForChild's arguments are the part name and its optional argument, time out. The time out defaults to one second. WaitForChild() checks for the part you specify as usual, however, if that part is nil, it would wait the amount of time in the time out. If it couldn't find it still, it would warn and return an infinite yield. In contrary to :FindFirstChild()
, it would error automatically if the argument specified is nil.
For example:
local brick = game.Workspace:FindFirstChild("Brick")
Since we have no part named "Brick" in Workspace, it would error However:
local brick = game.Workspace:WaitForChild("Brick")
It would wait for the amount of time in the timeout(remember, it defaults to one) and then warn
What I mean by making clean if-statements includes not having lengthy conditionals and etc. But your if statements don't really have that problem. In the condition, if (human ~= nil) and debounce == false then
, you can omit, or remove, the parenthesis and the ~= nil
. This looks much more cleaner: if human and debounce == false then
. This goes to another if-statement
Your function, getPlayers(humanoid)
is extra and unneeded. Instead, you can use hit to find the player by using the :GetPlayerFromCharacter()
method. Your getPlayers(humanoid)
works, but, it is just wastes your time when you could do all of that in one method.
What was a huge mistake in your script is that you have changed a GUI from StarterGui. This will not do anything because whatever in StarterGui will be cloned into PlayerGui(found in the player). How to fix this is by finding the PlayerGui in the player using :WaitForChild()
Here is the final code. If you have noticed a few changes, please read the bottom, it might answer your question.
--\\ Touched Components local part = script.Parent local debounce = false function onTouch(hit) -- I have changed "part" to "hit" because that fits much more better in here local human = hit.Parent:WaitForChild("Humanoid") -- Gets humanoid if human and debounce == false then -- Checks if humanoid is not nil debounce = true local player = players:GetPlayerFromCharacter(human.Parent) -- See, we used the :GetPlayerFromCharacter()! This simplifies your whole function if player == nil then return end local playerGui = player:WaitForChild("PlayerGui") local shopGui = playerGui:WaitForChild("ShopGui") local shopFrame = shopGui:WaitForChild("ShopFrame") shopFrame.Visible = true wait(2) else wait(2) debounce = false end end part.Touched:Connect(onTouch)
You have said that this script should be put into Filtering Enabled. I'll do that for you. You could pick the first answer and follow that, or, you could pick my answer.
Now, Filtering Enabled makes the server never trust the client. To make the server trust the client, we need to use Remote Events and Remote Functions to notify the server that it's not an exploit.
We will be using :FireClient()
since our GUI is in the Client, not in the server.
What we will need to do first is to make our Remote Event. We will put this in ReplicatedStorage(this is important because we want the server and client to access it.). I will name the RemoteEvent to "FrameVisibleRemoteEvent".
Your Local Script in StarterGui should look like this:
--\\ Services local repStorage = game:GetService("ReplicatedStorage") local players = game:GetService("Players") --\\ Player Components local player = players.LocalPlayer local playerGui = player:WaitForChild("PlayerGui") --\\ GUI's local shopGui = playerGui:WaitForChild("ShopGui") local shopFrame = shopGui:WaitForChild("ShopFrame") --\\ Network Data local frameVisible = repStorage:WaitForChild("FrameVisibleRemoteEvent") frameVisible.OnClientEvent:Connect(function() shopFrame.Visible = true end)
Your Server Script in you part should look like this:
--\\ Services local repStorage = game:GetService("RepStorage") --\\ Touched Components local part = script.Parent local debounce = false --\\ Network Data local frameVisible = repStorage:WaitForChild("FrameVisibleRemoteEvent") function onTouch(hit) local human = hit.Parent:WaitForChild("Humanoid") -- Gets humanoid if human and debounce == false then -- Checks if humanoid is not nil debounce = true local player = players:GetPlayerFromCharacter(human.Parent) if player == nil then return end frameVisible:FireClient(player) wait(2) else wait(2) debounce = false end end part.Touched:Connect(onTouch)
Now, the first answer that you have got in Filtering Enabled was a more general approach. My approach was very specific.
Indenting is crucial when typing clean code. You don't have to do this, however, if you wanted to come back to your code, you would be able to understand it. In contrary to not indenting, you might not be able to understand it.
You mustn't use StarterGui
for it. StarterGui contents get cloned to the player's PlayerGui
. They are like a template. What you should do is set the visibility of the frame in PlayerGui instead.
Server script:
local remote = Instance.new("RemoteEvent", game.ReplicatedStorage) remote.Name = "ToggleGui" local debounce = false function getPlayer(humanoid) local players = game.Players:GetPlayers() --you should use GetPlayers() rather than GetChildren() or children() for i = 1, #players do if players[i].Character.Humanoid == humanoid then return players[i] end end return nil end function onTouch(part) local human = part.Parent:findFirstChild("Humanoid") if (human ~= nil) and debounce == false then debounce = true local player = getPlayer(human) if (player == nil) then return end remote:FireClient(plr, "ShopGui", true) wait(2) else wait(2) debounce = false end end script.Parent.Touched:connect(onTouch)
Local script:
local plr = game.Players.LocalPlayer local remote = game.ReplicatedStorage:WaitForChild("ToggleGui") remote.OnClientEvent:Connect(function(name, bool) local gui = plr.PlayerGui:FindFirstChild(name, true) if gui then gui.Visible = bool end end)
I edited the script to make it FE compatible.
This works in Studio now but not in the real game, can someone please still help!?
local debounce = false function getPlayer(humanoid) local players = game.Players:GetPlayers() --you should use GetPlayers() rather than GetChildren() or children() for i = 1, #players do if players[i].Character.Humanoid == humanoid then return players[i] end end return nil end function onTouch(part) local human = part.Parent:FindFirstChild("Humanoid") if (human ~= nil) and debounce == false then debounce = true local player = getPlayer(human) if (player == nil) then return end player.PlayerGui.ShopGui.ShopFrame.Visible = true --this line, see? wait(2) else wait(2) debounce = false end end script.Parent.Touched:connect(onTouch)