User interface 在Roblox中动态创建GUI

User interface 在Roblox中动态创建GUI,user-interface,dynamic,lua,roblox,User Interface,Dynamic,Lua,Roblox,我正在使用lua和roblox studio编写我的第一个游戏。我有几个关于GUI的问题。我已经编写了一个非常基本的gui,它显示了可以加入游戏的四个团队的代码。下面是GUI的代码。它存在于StarterGUI中的本地脚本中: local UpdateGUI = game.ReplicatedStorage:WaitForChild("UpdateGUI") local StartGui = game.ReplicatedStorage:WaitForChild("StartGui") loca

我正在使用lua和roblox studio编写我的第一个游戏。我有几个关于GUI的问题。我已经编写了一个非常基本的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)
当玩家加入游戏时,有一个函数可以启动服务器端脚本中触发的标签。通过“启动标签”,我的意思是标签的透明度为1,当玩家加入时,该函数使其可见。有一个功能,每当任何玩家得分时都会更新标签,还有一个功能,当玩家延迟加入游戏时也会触发,以确保它拥有游戏中已有玩家的得分。就像我说的,这是我的第一场比赛,我专注于工作。现在我想正确地编写代码。我的目标是动态分配标签。也就是说,当玩家加入游戏时,标签是用代码创建的。特别是我希望标签之间的空间是动态设置的,这样无论有多少玩家,标签都会居中。我试着把标签做成“框架”的子标签,但标签改变了位置,很难操作。所以我想要一些关于如何在代码中设置的建议

我的目标是动态分配标签。也就是说,当玩家加入游戏时,标签是用代码创建的

可以使用与在工作区中创建实例相同的方法创建UI元素

local lblTeam = Instance.new("TextLabel")
lblTeam.TextTransparency = 0
lblTeam.TextStrokeTransparency = 0
lblTeam.Name = teamName
lblTeam.Parent = game.Players.LocalPlayer.PlayerGui.ScreenGui
我希望标签之间的空间可以动态设置,这样无论有多少玩家,标签都可以居中

在Roblox中,UI元素的布局方式是使用UDim2值表示大小和位置。 UDim2的构造函数如下所示:
UDim2.new(xScale、xOffset、yScale、yOffset)
。“比例”是指在该维度范围内父容器的百分比,而“偏移”是要添加的额外像素数。例如:

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手动放置这些对象,但我建议您使用一个对象并使用LayoutIndex属性为您自动放置对象。它将自动为您处理Position属性

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
我注意到当一个玩家死亡时,GUI会在重生时消失

ScreenGUI上有一个名为的属性,可以更改为false。这将保持用户界面,即使在球员重置

因为您是在代码中动态创建UI,所以应该注意不要意外地多次创建UI。这里是StarterPlayer>StarterPlayerScript和StarterPlayer>StarterCharacterScript之间的区别变得重要的地方。StarterPlayerScript中的LocalScript将在玩家首次加入时运行,StarterCharacterScript中的LocalScript将在玩家的角色每次重新加载时运行。因此,在创建UI时,请注意触发代码的位置


希望这有帮助

嗨,这很有用。非常感谢Kylaaa。唯一的问题是索引不是动态创建的?例如,一对玩家加入游戏,他们玩了一段时间,这时我们应该有两个标签。然后第三个玩家稍后加入。然后我们有三个标签。也许我可以通过远程事件在OnPlayerAdded函数中使用您编写的CreateTeamUI函数?因此,当一个玩家加入时,我可以通过计算数组来获得索引:#Players:GetPlayers()这有意义吗?是的,可以。另一个选项是保留一个局部变量“teamCount”,并在调用CreateTeamUI()时添加+1。然后使用它,而不是传入索引。