创建一个图形用户界面

*此内容使用人工智能(Beta)翻译,可能包含错误。若要查看英文页面,请点按 此处

现在游戏信息的大部分仍在输出窗口中,对玩家隐形。 因此,玩家可以通过查看图形用户界面(GUI)和脚本来了解游戏中发生了什么事情。 您将创建一个图形用户界面(GUI)并将其编码。

使用 GUI 显示信息

对于此游戏,显示一个文本标签,其中包括当前游戏状态和剩余玩家数。

中场休息时间
在比赛期间

设置图形用户界面

首先,创建一个 屏幕GUI 对象来持有不同的文本元素。当玩家移动相镜头时,屏幕GUI 会保持在屏幕上的同一个位置。

为了确保所有玩家都看到相同的显示,请将 GUI 放置在 StarterGui 文件夹。在游戏启动时,此文件夹将被复制到所有玩家。

  1. 在 StarterGui 文件夹中,创建一个新的屏幕图形用户界面。然后在屏幕图形用户界面中,添加一个名为 StatusText 的新 TextLabel。

  2. 要移动标签,在 Explorer 中,选择状态文本。然后,在游戏视查看中,将标签拖动到你想要的位置。你的数字可能与视频不同。标签还可以使用角落上的锚点进行调整。

脚本 GUI

要反映游戏中的更改,脚本需要更新 GUI 元素。例实例,游戏状态、是否是中场休息或正在进行的回合将被存储在 StringValue 中,使用本地脚本更新。

设置脚本

状态显示脚本将用于更新玩家的 GUI ,当游戏状态发生变更时。

  1. ReplicatedStorage 中,创建一个名为 DisplayValues 的文件夹。在该文件夹中,添加一个名为 Status 的字符串值。要在以后测试值,请给它一个临时值,例如“欢迎来到战斗!”。

  2. 在 StarterGui > ScreenGUI > Status 中,添加一个名为 StatusDisplay 的新本地脚本。影响 GUI 的脚本通常会被添加到该 GUI 元素。

  3. 打开状态显示并定义以下变量跟关注:

    • 复制存储服务

    • 显示值目录

    • 状态字符串值

    • 文本标签 - 使用 script.Parent .


      local ReplicatedStorage = game:GetService("ReplicatedStorage")
      local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
      local status = displayValues:WaitForChild("Status")
      local textLabel = script.Parent

改变文本标签

要改变标签中的文本,请使用一个已更改的事件,因为另一个脚本的状态字符串总是更改文本标签,所以文本标签的更新将被更新。

  1. updateText() 这个新函数中命名。在该函数中,将 textLabel 的文本属性设置为 status.Value


    local textLabel = script.Parent
    local function updateText()
    textLabel.Text = status.Value
    end
  2. 连接函数到 Changed 事件。


    local function updateText()
    textLabel.Text = status.Value
    end
    status.Changed:Connect(updateText)
  3. 因此玩家在游戏开始时可以看到最新状态,请在脚本结束时运行 updateText()


    local function updateText()
    textLabel.Text = status.Value
    end
    status.Changed:Connect(updateText)
    updateText()
  4. 运行游戏,确认您在显示中看到临时值。

创建显示管理器

在游戏期间,文本标签需要从游戏管理器、匹配管理器和可能是其他脚本获得信息。 因此,这些不同的脚本可以在需要时更新文本标签,创建名为显示管理器的模块脚本。

设置脚本

因为 DisplayManager 需要与其他脚本通信,它将是模块脚本。

  1. ServerStorage > ModuleScripts 中,创建一个名为 DisplayManager 的新模块脚本。 重命名模块表与脚本名称匹配。

  2. 为以关注中/正在关注添加本地变量: Replicated Storage、DisplayValues 文件夹、Status。


    local DisplayManager = {}
    -- 服务
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    -- 显示用于更新玩家 GUI 的值
    local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
    local status = displayValues:WaitForChild("Status")
    -- 本地函数
    -- 模块功能
    return DisplayManager
  3. 创建一个名为 updateStatus() 的新模块函数,该函数更新状态值中的字符串。其他脚本将能够调用此函数。


    -- 本地函数
    -- 模块功能
    function DisplayManager.updateStatus(newStatus)
    status.Value = newStatus
    end

更新文本状态

设置显示管理器后,可以在其他脚本中更新图形用户界面文本标签。作为 GUI 的第一个消息,通过 GameManager 脚本显示中场休息开始和结束。

  1. ServerScriptService > GameManager 中,创建一个名为 displayManager 的变量,并且在 ServerStorage 中需要显示管理器模块。


    -- 服务
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local ServerStorage = game:GetService("ServerStorage")
    local Players = game:GetService("Players")
    -- 模块脚本
    local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
    local roundManager = require(moduleScripts:WaitForChild("RoundManager"))
    local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
    local displayManager = require(moduleScripts:WaitForChild("DisplayManager"))
  2. 作为 第一行 在 while 真实做声明后,调用显示经理 > updateStatus() 并在一条关于等待玩家的消息。


    -- 事件
    local events = ServerStorage:WaitForChild("Events")
    local matchEnd = events:WaitForChild("MatchEnd")
    while true do
    displayManager.updateStatus("Waiting for Players")
    repeat
    print("Starting intermission")
    task.wait(gameSettings.intermissionDuration)
    until #Players:GetPlayers() >= gameSettings.minimumPlayers
    task.wait(gameSettings.transitionTime)
    matchManager.prepareGame()
    matchEnd.Event:Wait()
    end
  3. 在中场休息结束后,调用 updateStatus() 并通过串传递比赛即将开始的消息。由于您将在 GUI 上测试,因此删除两个打印声明来注意开始和结束中场休息。


    while true do
    displayManager.updateStatus("Waiting for Players")
    repeat
    task.wait(gameSettings.intermissionDuration)
    until #Players:GetPlayers() >= gameSettings.minimumPlayers
    displayManager.updateStatus("Get ready!")
    task.wait(gameSettings.transitionTime)
    matchManager.prepareGame()
    matchEnd.Event:Wait()
    end
  4. 测试游戏 使用不使用 您的最低玩家。 消息应该读取以关注中/正在关注内容:

    • 没有最低玩家: "Waiting for Players"
    • 使用最小玩家: "Get ready" .

排查提示

如果文本标签没有显示第一个消信息,或仍然显示“标签”,请尝试以下列中的一个。

  • 请确保在 StatusDisplay 本地脚本中, updateText() 在脚本底部被调用。这确保玩家得到最新消信息。
  • 检查StatusStringValue是否存在在ReplicatedStorage中。由于客户端-服务器关系的独特性,如果它在ServerStorage中,本地脚本将无法找到它。

显示匹配状态

在比匹配中,GUI 会显示两个数字:剩余玩家数量和时间。随着这些数字的变化,文本标签也会更改。

设置参数和函数

IntValues 将用于存储玩家数量和剩余时间。

  1. 在 ReplicatedStorage > DisplayValues 中,创建两个名为 PlayersLeft 和 TimeLeft 的 IntValue。

  2. 在显示管理器中,添加变量来存储剩余玩家和剩余时间值。


    local DisplayManager = {}
    -- 服务
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    -- 显示用于更新玩家 GUI 的值
    local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
    local status = displayValues:WaitForChild("Status")
    local playersLeft = displayValues:WaitForChild("PlayersLeft")
    local timeLeft = displayValues:WaitForChild("TimeLeft")
  3. 创建一个名为 updateMatchStatus() 的本地函数。然后将状态值设置为显示剩余时间和玩家数量。


    local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
    local status = displayValues:WaitForChild("Status")
    local playersLeft = displayValues:WaitForChild("PlayersLeft")
    local timeLeft = displayValues:WaitForChild("TimeLeft")
    -- 本地函数
    local function updateRoundStatus()
    status.Value = "Players Left: " .. playersLeft.Value .. " / Time Left: " .. timeLeft.Value
    end
  4. 对于 both IntValue 变量,连接 updateRoundStatus() 到 Changed 事件。


    -- 模块功能
    function DisplayManager.updateStatus(newStatus)
    status.Value = newStatus
    end
    playersLeft.Changed:Connect(updateRoundStatus)
    timeLeft.Changed:Connect(updateRoundStatus)
    return DisplayManager

显示玩家

然后,为显示游戏开始时玩家数量的代码。 后续课程将根据玩家从游戏中淘汰时更新 PlayersLeft 值。

  1. 在 PlayerManager 中,为 ReplicatedStorage 服务、DisplayValues 文件夹和 PlayersLeft IntValue 添加本地变量。


    local PlayerManager = {}
    -- 服务
    local Players = game:GetService("Players")
    local ServerStorage = game:GetService("ServerStorage")
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    -- 地图变量
    local lobbySpawn = workspace.Lobby.StartSpawn
    local arenaMap = workspace.Arena
    local spawnLocations = arenaMap.SpawnLocations
    -- 值
    local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
    local playersLeft = displayValues:WaitForChild("PlayersLeft")
  2. 通过将 playersLeft 设置为活跃玩家阵数组的大小来显示开始玩家数量。

    然后,在 sendPlayersToMatch() 的,在 for 循环下,类输入: playersLeft.Value = #activePlayers


    function PlayerManager.sendPlayersToMatch()
    local availableSpawnPoints = spawnLocations:GetChildren()
    for playerKey, whichPlayer in Players:GetPlayers() do
    table.insert(activePlayers, whichPlayer)
    local spawnLocation = table.remove(availableSpawnPoints, 1)
    preparePlayer(whichPlayer, spawnLocation)
    end
    playersLeft.Value = #activePlayers
    end

显示计时器

请记住模块脚本用于中心化类似代验证码。 由于计时器在 MatchManager 中跟踪,因此使用 Timer 脚本的函数更新 TimeLeft 值。 显示管理器将听取 TimeLeft 的更改,并更新匹配到新值。

  1. 在 MatchManager 中,创建变量来存储 ReplicatedStorage 服务、DisplayValues 文件夹和 TimeLeft 值。


    local MatchManager = {}
    -- 服务
    local ServerStorage = game:GetService("ServerStorage")
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    -- 模块脚本
    local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
    local playerManager = require(moduleScripts:WaitForChild("PlayerManager"))
    local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
    local timer = require(moduleScripts:WaitForChild("Timer"))
    -- 事件
    local events = ServerStorage:WaitForChild("Events")
    local matchStart = events:WaitForChild("MatchStart")
    -- 值
    local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
    local timeLeft = displayValues:WaitForChild("TimeLeft")
    local myTimer = timer.new()
  2. 找到 startTimer() 函数。 在 计时器的 Finished 事件后,复制并粘贴整个,高亮显示在下面的代码。 代码运行一个循环来更新计时器的 1> timeLeft1> 值,直到计时器仍然处于活动状态。


    while myTimer:isRunning() do
    -- 添加 + 1 会确保计时器显示为 1 而不是 0。
    timeLeft.Value = (math.floor(myTimer:getTimeLeft() + 1))
    -- 通过将时间设置为“等待”,它提供更准确的循环
    task.wait()
    end

    添加到时,代码应该看起来像下面的样本。


    local function startTimer()
    print("Timer started")
    myTimer:start(gameSettings.matchDuration)
    myTimer.finished:Connect(timeUp)
    while myTimer:isRunning() do
    -- 添加 + 1 会确保计时器显示为 1 而不是 0。
    timeLeft.Value = (math.floor(myTimer:getTimeLeft() + 1))
    -- 通过将时间设置为“等待”,它提供更准确的循环
    task.wait()
    end
    end
  3. 使用最小玩家启动游戏。 检查状态文本是否显示:

    • 正确的开始玩家数量。请记住,在未来的课程中,这个数字不会改变。
    • 时间每秒钟减少,直到它停止在 1 。

已完成的脚本

以下是完成脚本来重新检查您的工作。

游戏管理器脚本


-- 服务
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
-- 模块脚本
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local matchManager = require(moduleScripts:WaitForChild("MatchManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
local displayManager = require(moduleScripts:WaitForChild("DisplayManager"))
-- 事件
local events = ServerStorage:WaitForChild("Events")
local matchEnd = events:WaitForChild("MatchEnd")
while true do
displayManager.updateStatus("Waiting for Players")
repeat
task.wait(gameSettings.intermissionDuration)
until #Players:GetPlayers() >= gameSettings.minimumPlayers
displayManager.updateStatus("Get ready!")
task.wait(gameSettings.transitionTime)
matchManager.prepareGame()
matchEnd.Event:Wait()
end

显示管理器脚本


local DisplayManager = {}
-- 服务
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- 显示用于更新玩家 GUI 的值
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local status = displayValues:WaitForChild("Status")
local playersLeft = displayValues:WaitForChild("PlayersLeft")
local timeLeft = displayValues:WaitForChild("TimeLeft")
-- 本地函数
local function updateRoundStatus()
status.Value = "Players Left: " .. playersLeft.Value .. " / Time Left: " .. timeLeft.Value
end
-- 模块功能
function DisplayManager.updateStatus(newStatus)
status.Value = newStatus
end
playersLeft.Changed:Connect(updateRoundStatus)
timeLeft.Changed:Connect(updateRoundStatus)
return DisplayManager

MatchManager 脚本


local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- 模块脚本
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local playerManager = require(moduleScripts:WaitForChild("PlayerManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
local timer = require(moduleScripts:WaitForChild("Timer"))
-- 事件
local events = ServerStorage:WaitForChild("Events")
local matchStart = events:WaitForChild("MatchStart")
local matchEnd = events:WaitForChild("MatchEnd")
-- 值
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local timeLeft = displayValues:WaitForChild("TimeLeft")
local myTimer = timer.new()
-- 本地函数
local function timeUp()
print("Time is up!")
end
local function startTimer()
print("Timer started")
myTimer:start(gameSettings.matchDuration)
myTimer.finished:Connect(timeUp)
while myTimer:isRunning() do
-- 添加 + 1 会确保计时器显示为 1 而不是 0。
timeLeft.Value = (math.floor(myTimer:getTimeLeft() + 1))
-- 通过将时间设置为“等待”,它提供更准确的循环
task.wait()
end
end
-- 模块功能
function MatchManager.prepareGame()
playerManager.sendPlayersToMatch()
matchStart:Fire()
end
matchStart.Event:Connect(startTimer)
return MatchManager

显示状态的脚本


local ReplicatedStorage = game:GetService("ReplicatedStorage")
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local status = displayValues:WaitForChild("Status")
local textLabel = script.Parent
local function updateText()
textLabel.Text = status.Value
end
status.Changed:Connect(updateText)
updateText()