Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

My Gui won't open when my part gets touched?

Asked by 5 years ago
Edited 5 years ago

I have fixed this but I need to know where the scripts go that Kiriot22 fixed to work with FE.

0
It is "FindFirstChild." NOT "findFirstChild." Zafirua 1348 — 5y
0
Instead of changing the GUI in StarterGui, change it in the player's PlayerGui, which can be accessed by user.PlayerGui. what the player sees on their screen are descendants of their playergui Rare_tendo 3000 — 5y
0
Unless there are no players, getPlayer will return nil. hiimgoodpack 2009 — 5y

3 answers

Log in to vote
0
Answered by 5 years ago
Edited 5 years ago

There are multiple problems in your script

Deprecated Functions

You use the method :findFirstChild(). This is deprecated, or not recommended to use. To change this is by changing your deprecated method to :FindFirstChild()

You Should Use :WaitForChild() Instead of :FindFirstChild() If You Can

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

Making Clean if-statements

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

Extra Function

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.

You Should Never Make Changes In StarterGui

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()

Final Code

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)

How To Make This Script Compatible In Filtering Enabled

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.

PLEASE INDENT!

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.

0
I just need this FE compatible, thanks though K1ng_Phant0m 13 — 5y
0
You didn't state that your game is FE. I would've done that for you  saSlol2436 716 — 5y
0
Could you at least up-vote if it was a good answer? saSlol2436 716 — 5y
0
Sorry about not replying for awhile, thanks for the answer, very much appreciated, I understand RemoteEvents a bit better since I've asked this question also, thanks again. K1ng_Phant0m 13 — 5y
0
Your welcome saSlol2436 716 — 5y
Ad
Log in to vote
0
Answered by
Amiaa16 3227 Moderation Voter Community Moderator
5 years ago
Edited 5 years ago

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.

0
Thank you so much! K1ng_Phant0m 13 — 5y
0
so do I put both in the part or one in serverscriptservice other in part? K1ng_Phant0m 13 — 5y
0
You put the Server Script in the part and you put the Local Script any where the client can run (StarterGui,StarterPack etc.) saSlol2436 716 — 5y
Log in to vote
0
Answered by 5 years ago

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)
0
If your game is FE, you need to use RemoteEvents for it to work. I edited my answer to make it FE compatible. Amiaa16 3227 — 5y
0
ok ty K1ng_Phant0m 13 — 5y

Answer this question