I have following code:
game.Workspace.MapTrigger.Touched:Connect(function(hit) local plr = game.Players.LocalPlayer plr.PlayerGui.Map.ImageLabel.Visible = true end)
It's working like a charm... but on Studio Preview... with multiple people it's getting complicated. This GUI is shown to EVERYONE. I want it shown to only person that steps on part (touches).
Seems simple, but I failed so many times. (Also, if you know the solution, could you please inplement little simple Tween to animate gui opening? Thanks <3)
Before you read this, check the ending of the answer!
The reason why your script is not working is because your script is not compatable with FE (Filtering Enabled). In the past you could turn it off and on freely but ROBLOX released an update which forced it. Filtering Enabled seperates every client from eachother, the reason why it does that is because if someone ran a piece of code, it would only affect the one who ran it. If FE was off then it would replicate to the other clients. Click me to go to a robloxdev article about Filtering Enabled.
Now you may be wondering, if all the clients are seperated from each other then how can they communicate? Well they can communicate with each other via using ModuleScripts, Remote Events and Remote Functions. For your case we will only need to use Remote Events!
Let me talk about Remote Events, how they work and how should you use them. A remote event can be fired by the server or the client. When it is fired by a client then the client wants to make a request to the server to do something which will replicate to the other clients. Depends on how you use a remote event. If you are firing the client from the server then you want to make a change to the specific client. If you would like to fire all of the clients you can simply do that, there is a functions for that. If ROBLOX didn't add that function we could simply loop through all the players and fire the clients one by one. Now lets get into this more concretely.
So I told you how Remote Events work. But I haven't given the specific functions. So to fire the Client from the server you do
RemoteEvent:FireClient(player). As you can see inside the parantheses there is an argument called
player. Now why is there an argument? You might've already realised from my explaination. So the server wants fire a client, but he doesn't know who! So we are putting inside the brackets a player to fire. Now we fired the client. Now what? Well lets suppose we want the client to print "Hello!" in their output. But only in theirs and not the server's. What we do is that we receive the Remote Event request and we do something with it. In this case we print 'Hello!". This is how it would go:
RemoteEvent.OnClientEvent:Connect(function() print("Hello!") end)
That's it, literally! Note that the remote function that we are firing and receiving must be the same. Also we are running that script in the client. What about the client sends a request to the server so the server prints "Hello!" on their output (and the other clients since the changes from the server replicate to the other clients)and the name who fired the server in the output? Well it is the same logic but it is just a bit different. So lets start. Firstly lets fire the server.
RemoteEvent:FireServer(), that is all. We do not need an argument which defines the server because there is only 1 sever. Now from the server this is what we do:
RemoteEvent.OnServerEvent:Connect(function(plr) print("Hello! (Remote fired by "..plr.Name..")") end)
Should print "Hello! (Remote fired by "..plr.Name). Now you again may be wondering, why is there an argument between the function parentheses? Well the server sometimes needs to know which player is firing the server. If you didn't want to print the player's name then you could remove the plr argument because you wouldn't need it. It is optional depending on the way you are using the script.
"What if we wanted to fire all the clients from the server to them?". That is a question which is commonly asked by beginners. Now, you could do:
for i, v in pairs(game.Players:GetPlayers()) do RemoteEvent:FireClient(v) end
That is absolutely correct but, ROBLOX create a function for doing that! The way you use it is
OTHER IMPORTANT STUFF YOU MIGHT WANT TO KNOW: You can send arguments from the client to the server, and from the server to the client.
If you want a clearer and a more detailed explaination I would recommend you watching: this video. My explaination is not the best and I might've skipped something or sounded confusing so I recommend you watching the video. If you already read my post and you wanna watch the video it will just clear up the stuff that I said.
Now we know everything about remote events! Lets script what we need!
--Server local part = --locate the part that you want the event to occur upon touch local remote_event = --locate your remote event here, you will need one! part.Touched:Connect(function(hit) local hum = hit.Parent:FindFirstChild("Humanoid") or hit.Parent:FindFirstChild("Humanoid") local char = hum.Parent local plr = game.Players:GetPlayerFromCharacter(char) if plr then remote_event:FireClient(plr) end end)
--Client local remote_event = workspace--locate the same remote event as above local plr = game.Players.LocalPlayer remote_event.OnClientEvent:Connect(function() plr.PlayerGui.Map.ImageLabel.Visible = true end)
I do not think this needs any explaination because you know everything about remote events now and how they work so it should be simple to understand!
Ok so apparently there is another method which is more efficient. It is more efficient because it is shorter and only Client sided (no need for remote events). The reason why the post is so long is because I was going through every single detail and explaining it very carefully.
local part = workspace.Part part.Touched:Connect(function() game:GetService("Players").LocalPlayer.PlayerGui.Map.ImageLabel.Visible = true end)
The only reason why this is more efficient is because it is shorter to write and you do not need to mess around with the server and the remote events. I was thinking that since this method only works on the client and doesn't mess around with the server or remote events I thought it would be much faster becuase I thought remote events would have a big delay. Turns out my method ran as soon as the server ran. So no delay at all. And about the Client method? The number turned out to be negative. The test I ran told me that the Client method was around 0.0001 seconds faster. I mean the speed doesn't matter in this case since it is not like you are going to touch the brick as soon as you join but yeah.
P.S: Spent 40 minutes writing that @[email protected]
To do this, you'll have to go through the player GUI. How do you do that? very simple.
This short line goes through the local player's playergui. Now let's pick an event, for example mouse button 1 click.
game.StarterGui.ScreenGui.Frame.MouseButton1Click:Connect(function() game.Players.LocalPlayer.PlayerGui.ScreenGui.Frame.Visible = true end)
Basically, when this event is happening, it will create a new function, and it will be runned. And this function will make the GUI be only visible to the local player.
I hope it helped.