1
votes

I am coding my first game using lua and roblox studio. I have a couple of questions regarding GUI. I have coded a very rudimentary gui that displays the code of the four teams that can join the game. Here is the code for the GUI. It lives in a local script inside StarterGUI:

local UpdateGUI = game.ReplicatedStorage:WaitForChild("UpdateGUI")
local StartGui = game.ReplicatedStorage:WaitForChild("StartGui")
local UpdateAllScoresLateArrival = game.ReplicatedStorage:WaitForChild("UpdateAllScoresLateArrival")

local function updateAllLabelsLateArrival(redPoints, bluePoints, yellowPoints, greenPoints)
    game.Players.LocalPlayer.PlayerGui.ScreenGui.RedTeam.Text = redPoints
    game.Players.LocalPlayer.PlayerGui.ScreenGui.BlueTeam.Text = bluePoints
    game.Players.LocalPlayer.PlayerGui.ScreenGui.YellowTeam.Text = yellowPoints
    game.Players.LocalPlayer.PlayerGui.ScreenGui.GreenTeam.Text = greenPoints
end

local function UpdateLabel(plr, points)
    if plr.team.Name == "Really red Team" then
    game.Players.LocalPlayer.PlayerGui.ScreenGui.RedTeam.Text = points
    elseif plr.team.Name == "Really blue Team" then
    game.Players.LocalPlayer.PlayerGui.ScreenGui.BlueTeam.Text = points
    elseif plr.team.Name == "New Yeller Team" then
    game.Players.LocalPlayer.PlayerGui.ScreenGui.YellowTeam.Text = points
    elseif plr.team.Name == "Lime green Team" then
    game.Players.LocalPlayer.PlayerGui.ScreenGui.GreenTeam.Text = points
    end
end

local localPlayer = game.Players.LocalPlayer


local function StartLabel(player)
    if player.Team.Name == "Really red Team" then

    game.Players.LocalPlayer.PlayerGui.ScreenGui.RedTeam.TextTransparency = 0
    game.Players.LocalPlayer.PlayerGui.ScreenGui.RedTeamTag.TextTransparency = 0

    game.Players.LocalPlayer.PlayerGui.ScreenGui.RedTeam.TextStrokeTransparency = 0
    game.Players.LocalPlayer.PlayerGui.ScreenGui.RedTeamTag.TextStrokeTransparency = 0

    game.Players.LocalPlayer.PlayerGui.ScreenGui.RedTeamTag.BackgroundTransparency = 0.5

    elseif player.Team.Name == "Really blue Team" then

    game.Players.LocalPlayer.PlayerGui.ScreenGui.BlueTeam.TextTransparency = 0
    game.Players.LocalPlayer.PlayerGui.ScreenGui.BlueTeamTag.TextTransparency = 0
    game.Players.LocalPlayer.PlayerGui.ScreenGui.BlueTeam.TextStrokeTransparency = 0
    game.Players.LocalPlayer.PlayerGui.ScreenGui.BlueTeamTag.TextStrokeTransparency = 0
    game.Players.LocalPlayer.PlayerGui.ScreenGui.BlueTeamTag.BackgroundTransparency = 0.5

    elseif player.Team.Name == "New Yeller Team" then

    game.Players.LocalPlayer.PlayerGui.ScreenGui.YellowTeam.TextTransparency = 0
    game.Players.LocalPlayer.PlayerGui.ScreenGui.YellowTeamTag.TextTransparency = 0
    game.Players.LocalPlayer.PlayerGui.ScreenGui.YellowTeam.TextStrokeTransparency = 0
    game.Players.LocalPlayer.PlayerGui.ScreenGui.YellowTeamTag.TextStrokeTransparency = 0
    game.Players.LocalPlayer.PlayerGui.ScreenGui.YellowTeamTag.BackgroundTransparency = 0.5

    elseif player.Team.Name == "Lime green Team" then

    game.Players.LocalPlayer.PlayerGui.ScreenGui.GreenTeam.TextTransparency = 0
    game.Players.LocalPlayer.PlayerGui.ScreenGui.GreenTeamTag.TextTransparency = 0
    game.Players.LocalPlayer.PlayerGui.ScreenGui.GreenTeam.TextStrokeTransparency = 0
    game.Players.LocalPlayer.PlayerGui.ScreenGui.GreenTeamTag.TextStrokeTransparency = 0
    game.Players.LocalPlayer.PlayerGui.ScreenGui.GreenTeamTag.BackgroundTransparency = 0.5
    end


end


UpdateGUI.OnClientEvent:Connect(UpdateLabel)

StartGui.OnClientEvent:Connect(StartLabel)

UpdateAllScoresLateArrival.OnClientEvent:Connect(updateAllLabelsLateArrival)

There is a function that starts the label that is triggered in a server side script when a player joins the game. By ''start the label'' I mean that the labels are there with a transparency of 1 and the function makes them visible when a player joins. There is a function that updates the label everytime any player scores, and a function that is triggered also when a player joins the game late to make sure it has the scores of the players already in the game. Like I said this is my first game and I was focusing on things working. Now I would like to code it properly. My goal is that the labels are allocated dynamically. That is, when a player joins the game, the label is created in code. Particularly I would want the space between the labels to be set dynamically so that the labels are centred regardless of how many players. I tried making the labels a child of a ''frame'' but the labels changed place and were difficult to manipulate. So I would like some advice as to how to set this up in code.

1

1 Answers

1
votes

My goal is that the labels are allocated dynamically. That is, when a player joins the game, the label is created in code

You can create UI elements the same way you create Instances in the Workspace.

local lblTeam = Instance.new("TextLabel")
lblTeam.TextTransparency = 0
lblTeam.TextStrokeTransparency = 0
lblTeam.Name = teamName
lblTeam.Parent = game.Players.LocalPlayer.PlayerGui.ScreenGui

I would want the space between the labels to be set dynamically so that the labels are centered regardless of how many players there are.

The way UI elements are laid out in Roblox are with UDim2 values for Size and Position. A UDim2's constructor looks like this : UDim2.new(xScale, xOffset, yScale, yOffset). Scale refers to with percentage of the parent container should this dimension span, and Offset are the number of pixels extra to add. So some examples :

local lbl = Instance.new("TextLabel")
lbl.Size = UDim2.new(0, 50, 0, 10) -- 50 pixel wide and 10 pixel tall
lbl.Size = UDim2.new(1, 0, 1, 0) -- 100% wide by 100% tall
lbl.Size = UDim2.new(1, -10, 1, -10) -- 100% wide and tall, minus 10 pixels on both bottom and right

-- assuming no changes to AnchorPoint...
lbl.Position = UDim2.new(0, 0, 0, 0) -- upper left corner is upper left corner of parent
lbl.Position = UDim2.new(0.5, 0, 0.5, 0) -- upper left corner is dead center
lbl.Position = UDim2.new(1, 0, 0, 0) -- upper left corner is offscreen on the right

Now, if you want your stuff to be dynamically placed, you could manually place these objects using Positions, but I would recommend using a UIListLayout object and using the LayoutIndex property to automatically place objects for you. It will automatically handle the Position property for you.

local function createTeamUI(name, parent, teamName, index)
    -- make a small frame to hold each team UI
    -- looks like : [[  Team Tag Label  ][ Team Points Label ]]
    local teamFrm = Instance.new("Frame")
    teamFrm.BackgroundTransparency = 1
    teamFrm.Size = UDim2.new(1, 0, 0, 30) -- relative to parent : 100% wide, 30px tall
    teamFrm.Name = name
    teamFrm.LayoutIndex = index

    local lblTeamTag = Instance.new("TextLabel", teamFrm)
    lblTeamTag.TextTransparency = 0
    lblTeamTag.TextStrokeTransparency = 0
    lblTeamTag.Name = "TeamTag"
    lblTeamTag.Text = teamName
    lblTeamTag.Size = UDim2.new(0.5, 0, 1, 0) -- relative to teamFrm : 50% wide, 100% tall
    lblTeam.Position = UDim2.new(0, 0, 0, 0)

    local lblPoints = Instance.new("TextLabel", teamFrm)
    lblPoints.TextStrokeTransparency = 0
    lblPoints.BackgroundTransparency = 0.5
    lblPoints.Name = "Points"
    lblPoints.Text = "0"
    lblPoints.Size = UDim2.new(0.5, 0, 1, 0) -- relative to teamFrm
    lblPoints.Position = UDim2.new(0.5, 0, 0, 0)

    -- optimization : set the parent last
    teamFrm.Parent = parent
    return teamFrm
end

local function createAllTeamLabels()
    -- creates a list of UI
    local frm = Instance.new("Frame")
    frm.Name = "Teams"
    frm.Size = UDim2.new(0.3, 0, 1, 0)
    frm.BackgroundTransparency = 1.0

    local layout = Instance.new("UIListLayout")
    layout.LayoutOrder = Enum.SortOrder.LayoutIndex
    layout.FillDirection = Enum.FillDirection.Vertical
    layout.Padding = UDim.new(0, 10) -- 10 pixels between each element in the list

    local frmTeamA = createTeamLabel("RedTeam", frm, "Really Red Team", 0)
    local frmTeamB = createTeamLabel("BlueTeam", frm, "Blue Team", 1)
    local frmTeamC = createTeamLabel("GreenTeam", frm, "Green Team", 2)

    frm.Parent = game.Players.LocalPlayer.PlayerGui.ScreenGui
end

local function updatePoints(teamName, points)
    game.Players.LocalPlayer.PlayerGui.ScreenGui.Teams[teamName].Points.Text = tostring(points)
end

I have noticed that when a player dies, the GUI disappears on respawn

There is a property on ScreenGuis called ResetOnSpawn that you can change to false. That will keep the UI around even after a player resets.

Since you are making your UI dynamically in code, you should be careful that you aren't accidentally creating the UI multiple times. Here's where the differences between StarterPlayer > StarterPlayerScripts and StarterPlayer > StarterCharacterScripts become important. A LocalScript inside StarterPlayerScripts will run when the player first joins, and a LocalScript inside StarterCharacterScripts will run every time the player's character reloads. So be careful where you fire the code to create the UI.

Hope this helps!