在 Roblox 中动态创建的 GUI

Dynamically created GUI in Roblox

我正在使用 lua 和 roblox studio 编写我的第一款游戏。我有几个关于 GUI 的问题。我编写了一个非常基本的图形用户界面,显示了可以加入游戏的四个团队的代码。这是 GUI 的代码。它位于 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)

有一个函数可以启动当玩家加入游戏时在服务器端脚本中触发的标签。 ''start the label'' 我的意思是标签在那里的透明度为 1,并且该函数使它们在玩家加入时可见。有一个函数会在每次任何玩家得分时更新标签,还有一个函数会在玩家晚加入游戏时触发,以确保它具有已经在游戏中的玩家的分数。就像我说的,这是我的第一场比赛,我专注于工作。现在我想正确编码。我的目标是动态分配标签。也就是说,当玩家加入游戏时,标签是在代码中创建的。特别是我希望动态设置标签之间的 space,以便无论有多少玩家,标签都居中。我尝试使标签成为 ''frame'' 的子标签,但标签改变了位置并且难以操作。所以我想要一些关于如何在代码中设置它的建议。

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

您可以像在工作区中创建实例一样创建 UI 元素。

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.

Roblox 中 UI 元素的布局方式是使用 UDim2 大小和位置值。 UDim2 的构造函数如下所示:UDim2.new(xScale, xOffset, yScale, yOffset)。 Scale 是指父容器的百分比,应该是这个尺寸跨度,Offset 是额外添加的像素数。所以一些例子:

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

现在,如果您希望动态放置您的东西,您可以可以使用 Positions 手动放置这些对象,但我建议使用 UIListLayout 对象并使用LayoutIndex 属性 自动为您放置对象。它会自动为您处理职位属性。

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

ScreenGuis 上有一个名为 ResetOnSpawn 的 属性,您可以将其更改为 false。即使在玩家重置后,这也会使 UI 保持不变。

由于您是在代码中动态创建 UI,因此您应该注意不要意外地多次创建 UI。 StarterPlayer > StarterPlayerScriptsStarterPlayer > StarterCharacterScripts 之间的区别变得很重要。当玩家首次加入时,StarterPlayerScripts 中的 LocalScript 将 运行,每次玩家角色重新加载时,StarterCharacterScripts 中的 LocalScript 将 运行。所以要小心你在哪里触发代码来创建 UI.

希望对您有所帮助!