I'm trying to use the PlayerAdded to make a screen gui disappear and make another one appear. It makes both guis appear though. I also am trying to make the player not spawn in when they join the game and that doesn't work either.
game.Player.CharacterAutoLoads = false
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player)
game.StarterGui.StartScreenFrame.Visible = true
game.StarterGui.PlayGui.Visible = false
end)
Take a look at the documentation for StarterGui.
When a Players’ character respawns, the contents of their PlayerGui is emptied. Children of the StarterGui are then copied (along with their descendants) into the
PlayerGui.
Stuff in the StarterGui acts as a template. The actual labels that show up on a player's screen are found in the player's PlayerGui. Your code is modifying the template, not the elements that are cloned to the PlayerGui.
Normally, to fix your problem, you would just need the correct paths to the UI elements. But you have a complicating factor, you've specified that game.Players.CharacterAutoLoads = false. This means that stuff in the StarterGui doesn't get cloned into the PlayerGui until the player's character spawns.
So I would recommend a few things :
Move your UI Elements into ReplicatedStorage, this will prevent UI element duplication when you eventually tell your character to spawn into the world.
Clone the elements into each player's UI manually. This will make the UI elements show up.
Configure the cloned elements. This way you can script the UI behaviors yourself.
And then update your Script like this :
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- get a reference to the UI templates
local startScreen = ReplicatedStorage.StartScreenFrame
local playScreen = ReplicatedStorage.PlayGui
-- disable character's auto loading
Players.CharacterAutoLoads = false
-- listen for when players first join the game
Players.PlayerAdded:Connect(function(player)
-- add the UI Elements to the PlayerGui
local startGui = startScreen:Clone()
startGui.Visible = true
startGui.Parent = player.PlayerGui
local playGui = playScreen:Clone()
playGui.Visible = false -- enable this later
playGui.Parent = player.PlayerGui
end)
Be aware that because you are manually placing UI Elements into the PlayerGui, you should be careful that when a Player dies and respawns, their PlayerGui will be cleared. You can avoid this by setting the ResetOnSpawn property to false on each ScreenGui.
Related
I have a system in my game where when a player steps on a checkpoint, a Stage value in the leaderboard will go up, and then that value is saved to that player's userId.
I want there to be a button that resets that value back to 0, and this is the code I tried for it.
local textButton = script.Parent
local Players = game:GetService("Players")
textButton.MouseButton1Up:Connect(function()
local player = game.Players.LocalPlayer
local stage = Players:WaitForChild(player):WaitForChild("leaderstats").Stage
if stage.Value > 1 then
stage.Value = 1
end
end)
I've tried debugging it by putting print commands in different places to see where the code gets, and when I try to run print(stage) it does not show anything.
LocalScripts cannot change the value on the server. To change a value once a button is clicked, RemoteEvents should be used.
There is a page documenting about them here: https://create.roblox.com/docs/scripting/networking/remote-events-and-functions
To use a RemoteEvent, first you need to put it in a place that is replicated across the server and the client. A good example of this would be to put it in ReplicatedStorage. After that, you need to set up a script that listens for the .OnServerEvent event of the RemoteEvent. To do this, you need to connect a function. As seen in your script, you already know how to do this. So I will get straight to the point.
On the server, set up a script that listens for .OnServerEvent. Next, on the client, edit your script to fire the client instead of trying to set the value. Go back to the server script, and set the value there. The event also passes the Player object, so you can utilize that to actually reset the value.
TLDR;
LocalScript inside of your TextButton:
local textButton = script.Parent
local Players = game:GetService("Players")
local RemoteEvent = 'RemoteEvent location'
textButton.MouseButton1Up:Connect(function()
RemoteEvent:FireServer()
end)
Server Script in anywhere, preferably ServerScriptService:
RemoteEvent.OnServerEvent:Connect(function(player)
local Players = game:GetService("Players")
local stage = Players:WaitForChild(player):WaitForChild("leaderstats").Stage
if stage.Value > 1 then
stage.Value = 1
end
end)
Good luck!
Basically what I've done so far is add a boolValue to every player, and if that boolValue is set to true, they can see invisible people, if it is false, they can't. I am clueless about the code currently so I have no idea how to begin. I'm also changing the value of the Bool Value through a tool.
The key to making one player invisible only to certain players is the understanding that any changes made to the world in a LocalScript are only visible to that player. They are not replicated between other clients. So, if we can set up a system where LocalScripts can be told to turn a specific player invisible, that player will vanish from their screen and their screen only.
So if we had that system, Player Two could say, "Hey game server, could you let the people know to turn me invisible!". That message would go up to the server, the server would send it out to a bunch of different clients, and each client would make the change locally using their LocalScripts, and the player would effectively turn invisible on their screen.
So even though Player Two looks to be invisible to Players One and Three, to the game server, nothing is different or out of the ordinary, the changes are localized entirely to each player's version of the world.
One way to do this is to use a setup like this :
A Tool in StarterPack to allow players to control their visibility
A BoolValue inside that tool to hold onto the visiblity state
A LocalScript to control the tool's logic
A RemoteEvent in ReplicatedStorage
A Script in ServerScriptService to handle the event routing
In the LocalScript, you would have something like this :
local tool = script.Parent
local IsHidden = tool:WaitForChild("IsHidden", 5)
local TogglePlayerVisible = game.ReplicatedStorage.TogglePlayerVisible
local localPlayer = game.Players.LocalPlayer
-- debug
tool.Name = "Turn Invisible"
tool.RequiresHandle = false
IsHidden.Value = false
-- 1) When a player activates the tool, flip the BoolValue
tool.Activated:Connect(function()
IsHidden.Value = not IsHidden.Value
tool.Name = IsHidden.Value and "Become Visible" or "Turn Invisible"
end)
-- 2) When the BoolValue changes, tell the server about it
IsHidden.Changed:Connect(function(updatedValue)
TogglePlayerVisible:FireServer(updatedValue)
end)
-- 4) When the server tells us a player has used the tool, make that player invisible locally
TogglePlayerVisible.OnClientEvent:Connect(function(player, isHidden)
local invisible = 1.0
local visible = 0.0
-- if we are the one who sent it, only make us a little invisible
if (player.Name == localPlayer.Name) then
invisible = 0.7
end
-- loop over all of the parts in a player's Character Model and hide them
for _, part in ipairs(player.Character:GetDescendants()) do
local shouldTogglePart = true
-- handle exceptions
if not (part:IsA("BasePart") or part:IsA("Decal")) then
shouldTogglePart = false
elseif part.Name == "HumanoidRootPart" then
shouldTogglePart = false
end
-- hide or show all the parts and decals
if shouldTogglePart then
part.Transparency = isHidden and invisible or visible
end
end
end)
And in the Script, you would have something like this :
local TogglePlayerVisible = game.ReplicatedStorage.TogglePlayerVisible
-- 3) whenever a player triggers this event, send it out to all players
TogglePlayerVisible.OnServerEvent:Connect(function(player, isVisible)
TogglePlayerVisible:FireAllClients(player, isVisible)
end)
If you would like only specific players to not see a player, then you can modify step 3 so that instead of using TogglePlayerVisible:FireAllClients, you would specifically choose which players to send the message to using FireClient.
I am trying to create a TextLabel that changes every 5 seconds. I have this code, but it doesn't work.
local player = game.Players:GetPlayerFromCharacter(part.Parent) —this is our gateway to getting the PlayerGui object.
local PlayerUI = player:WaitForChild(“PlayerGui”)
local txtLabel = PlayerUI[“Welcome_Text”].TextLabel
while x < 1 do
wait(5)
txtLabel.Text = “Welcome to The Shadow Realm!”
wait(5)
txtLabel.Text = “Warning: This game contains scenes that may be too scary for some roblox players”
end
I am getting an error message that says.
ServerScriptService.Script:2: attempt to index global 'part' (a nil value)
I don't know where to put my gui.
If I am correctly understanding what you are trying to do, you should be able to create a ScreenGui and place it in StartGui so that every player will have it copied to his PlayerGui when he joins the game. You could place a LocalScript inside of that GUI that would control the text on screen.
I see your LocalScript looking something like this:
-- Customize names on your own; these are just generic placeholders.
-- The structure of the GUI would look like this:
--
-- ScreenGui
-- LocalScript
-- Frame
-- TextLabel
local WELCOME = "Welcome to the Shadow Realm!"
local WARNING = "Warning! This game contains scenes that may be too scary for some players"
local runService = game:GetService("RunService")
local gui = script.Parent
local frame = gui.Frame
local label = frame.TextLabel
local function update_text()
label.Text = WELCOME
wait(5)
label.Text = WARNING
return
end
runService.RenderStepped:Connect(update_text)
Making this a LocalScript within a client-side GUI shifts the overhead to the client and eliminates the need to use the method Players::GetPlayerFromCharacter.
i'm making a script that detects a person using their name however I can't seem to get it working. Please also point out any mistakes I have done in my script it would help a lot.
game.Workspace:WaitForChild("Console")
print("Waited")
game.Players.PlayerAdded:Connect(function(plr)
print("Connected")
if game.Workspace.Console and plr.Name == "wojciechpa2007" then
local Console = game.Lighting.Console:Clone()
Console.Parent = plr.Startergui
print("Cloned")
elseif
not game.Workspace.Console and plr.Name == "wojciechpa2007" then
plr.Startergui.Console:Destroy()
print("Destroyed")
end
end)
Heyo,
This script has a race-condition in it. Your first line game.Workspace:WaitForChild("Console") will block execution of the rest of your script until the object is loaded, or a timeout is reached.
This means that it is possible that a player could join the game before the script can listen for the game.Players.PlayerAdded signal.
Also StarterGui does not exist on specific player. It exists at the game level and is a bucket that dumps its stuff into a Player's PlayerGui when that player's character loads into the game.
So to fix your script, you could try something like this :
-- right away connect to the PlayerAdded signal
game.Players.PlayerAdded:Connect(function(plr)
print("Player Joined!", plr.Name, plr.UserId)
-- do something special if wojciechpa2007 joins
if plr.Name == "wojciechpa2007" then
print("wojciechpa2007 joined! Adding console!")
-- add the special console into the player's PlayerGui for when they load
local Console = game.Lighting.Console:Clone()
Console.Parent = plr.PlayerGui
end
end)
Some recommendations and things to be careful about here :
It's safer to check a player's UserId than it is to check their name. Roblox lets you change your name, but you UserId is always the same.
Putting something into your StarterGui will make it show up in your PlayerGui the next time your character loads. But if your character is already loaded, you won't see it until the next time you respawn.
If your Console object is some kind of GUI element, make sure that it is parented to a ScreenGui object before you insert it into the Player. Otherwise it just won't show up.
Hope this helps!
I'm pretty new to ROBLOX development and don't really know how to make the objects talk just yet.
I have 16 cells all with an individual open and close button. Those work. I want to create a button that will open all doors at once.
function onClicked()
script.Parent.Parent.Door.Transparency = 1
script.Parent.Parent.Door.CanCollide= false
end
script.Parent.ClickDetector.MouseClick:connect(onClicked)
The above function is on each cell and works. I would like to loop through each one and fire it when I click a different button. I've been looking into getting each object with the same names but haven't been able to iterate through it.
The below code is my attempt to get it to fire off each one!
local part = workspace.OpenButton
local clickDetector = Instance.new("ClickDetector")
local function onMouseClick(player)
for _, child in pairs(workspace.PrisonCell:GetChildren()) do
print(child)
child:connect(child.Door.onClicked)
end
end
clickDetector.Parent = part
part.Parent = workspace
clickDetector.MouseClick:connect(onMouseClick)
Any help with this would be greatly appreciated!
You could do something similar to this to open all of the prison doors at once:
local part = workspace.OpenButton
local clickDetector = Instance.new("ClickDetector")
local function onMouseClick(player)
for _, child in pairs(workspace.PrisonCell:GetChildren()) do
child.Door.Transparency = 1
child.Door.CanCollide = false
end
end
clickDetector.Parent = part
part.Parent = workspace
clickDetector.MouseClick:connect(onMouseClick)
The downside to using the solution above is that if you want to change the door opening script, you would have to change it in both the individual cell buttons as well as this master button script. If you think this might be a problem in the future, I would consider writing a master script somewhere in ServerScriptService that uses BindableEvents for communcation with the button clicking scripts in order to keep the door opening function in one place.