现在游戏信息的大部分仍在输出窗口中,对玩家隐形。 因此,玩家可以通过查看图形用户界面(GUI)和脚本来了解游戏中发生了什么事情。 您将创建一个图形用户界面(GUI)并将其编码。
使用 GUI 显示信息
对于此游戏,显示一个文本标签,其中包括当前游戏状态和剩余玩家数。
设置图形用户界面
首先,创建一个 屏幕GUI 对象来持有不同的文本元素。当玩家移动相镜头时,屏幕GUI 会保持在屏幕上的同一个位置。
为了确保所有玩家都看到相同的显示,请将 GUI 放置在 StarterGui 文件夹。在游戏启动时,此文件夹将被复制到所有玩家。
在 StarterGui 文件夹中,创建一个新的屏幕图形用户界面。然后在屏幕图形用户界面中,添加一个名为 StatusText 的新 TextLabel。
要移动标签,在 Explorer 中,选择状态文本。然后,在游戏视查看中,将标签拖动到你想要的位置。你的数字可能与视频不同。标签还可以使用角落上的锚点进行调整。
脚本 GUI
要反映游戏中的更改,脚本需要更新 GUI 元素。例实例,游戏状态、是否是中场休息或正在进行的回合将被存储在 StringValue 中,使用本地脚本更新。
设置脚本
状态显示脚本将用于更新玩家的 GUI ,当游戏状态发生变更时。
在 ReplicatedStorage 中,创建一个名为 DisplayValues 的文件夹。在该文件夹中,添加一个名为 Status 的字符串值。要在以后测试值,请给它一个临时值,例如“欢迎来到战斗!”。
在 StarterGui > ScreenGUI > Status 中,添加一个名为 StatusDisplay 的新本地脚本。影响 GUI 的脚本通常会被添加到该 GUI 元素。
打开状态显示并定义以下变量跟关注:
复制存储服务
显示值目录
状态字符串值
文本标签 - 使用 script.Parent .
local ReplicatedStorage = game:GetService("ReplicatedStorage")local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")local status = displayValues:WaitForChild("Status")local textLabel = script.Parent
改变文本标签
要改变标签中的文本,请使用一个已更改的事件,因为另一个脚本的状态字符串总是更改文本标签,所以文本标签的更新将被更新。
在 updateText() 这个新函数中命名。在该函数中,将 textLabel 的文本属性设置为 status.Value。
local textLabel = script.Parentlocal function updateText()textLabel.Text = status.Valueend连接函数到 Changed 事件。
local function updateText()textLabel.Text = status.Valueendstatus.Changed:Connect(updateText)因此玩家在游戏开始时可以看到最新状态,请在脚本结束时运行 updateText()。
local function updateText()textLabel.Text = status.Valueendstatus.Changed:Connect(updateText)updateText()运行游戏,确认您在显示中看到临时值。
创建显示管理器
在游戏期间,文本标签需要从游戏管理器、匹配管理器和可能是其他脚本获得信息。 因此,这些不同的脚本可以在需要时更新文本标签,创建名为显示管理器的模块脚本。
设置脚本
因为 DisplayManager 需要与其他脚本通信,它将是模块脚本。
在 ServerStorage > ModuleScripts 中,创建一个名为 DisplayManager 的新模块脚本。 重命名模块表与脚本名称匹配。
为以关注中/正在关注添加本地变量: Replicated Storage、DisplayValues 文件夹、Status。
local DisplayManager = {}-- 服务local ReplicatedStorage = game:GetService("ReplicatedStorage")-- 显示用于更新玩家 GUI 的值local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")local status = displayValues:WaitForChild("Status")-- 本地函数-- 模块功能return DisplayManager创建一个名为 updateStatus() 的新模块函数,该函数更新状态值中的字符串。其他脚本将能够调用此函数。
-- 本地函数-- 模块功能function DisplayManager.updateStatus(newStatus)status.Value = newStatusend
更新文本状态
设置显示管理器后,可以在其他脚本中更新图形用户界面文本标签。作为 GUI 的第一个消息,通过 GameManager 脚本显示中场休息开始和结束。
在 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"))作为 第一行 在 while 真实做声明后,调用显示经理 > updateStatus() 并在一条关于等待玩家的消息。
-- 事件local events = ServerStorage:WaitForChild("Events")local matchEnd = events:WaitForChild("MatchEnd")while true dodisplayManager.updateStatus("Waiting for Players")repeatprint("Starting intermission")task.wait(gameSettings.intermissionDuration)until #Players:GetPlayers() >= gameSettings.minimumPlayerstask.wait(gameSettings.transitionTime)matchManager.prepareGame()matchEnd.Event:Wait()end在中场休息结束后,调用 updateStatus() 并通过串传递比赛即将开始的消息。由于您将在 GUI 上测试,因此删除两个打印声明来注意开始和结束中场休息。
while true dodisplayManager.updateStatus("Waiting for Players")repeattask.wait(gameSettings.intermissionDuration)until #Players:GetPlayers() >= gameSettings.minimumPlayersdisplayManager.updateStatus("Get ready!")task.wait(gameSettings.transitionTime)matchManager.prepareGame()matchEnd.Event:Wait()end测试游戏 使用 和 不使用 您的最低玩家。 消息应该读取以关注中/正在关注内容:
- 没有最低玩家: "Waiting for Players" 。
- 使用最小玩家: "Get ready" .
排查提示
如果文本标签没有显示第一个消信息,或仍然显示“标签”,请尝试以下列中的一个。
- 请确保在 StatusDisplay 本地脚本中, updateText() 在脚本底部被调用。这确保玩家得到最新消信息。
- 检查StatusStringValue是否存在在ReplicatedStorage中。由于客户端-服务器关系的独特性,如果它在ServerStorage中,本地脚本将无法找到它。
显示匹配状态
在比匹配中,GUI 会显示两个数字:剩余玩家数量和时间。随着这些数字的变化,文本标签也会更改。
设置参数和函数
IntValues 将用于存储玩家数量和剩余时间。
在 ReplicatedStorage > DisplayValues 中,创建两个名为 PlayersLeft 和 TimeLeft 的 IntValue。
在显示管理器中,添加变量来存储剩余玩家和剩余时间值。
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")创建一个名为 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.Valueend对于 both IntValue 变量,连接 updateRoundStatus() 到 Changed 事件。
-- 模块功能function DisplayManager.updateStatus(newStatus)status.Value = newStatusendplayersLeft.Changed:Connect(updateRoundStatus)timeLeft.Changed:Connect(updateRoundStatus)return DisplayManager
显示玩家
然后,为显示游戏开始时玩家数量的代码。 后续课程将根据玩家从游戏中淘汰时更新 PlayersLeft 值。
在 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.StartSpawnlocal arenaMap = workspace.Arenalocal spawnLocations = arenaMap.SpawnLocations-- 值local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")local playersLeft = displayValues:WaitForChild("PlayersLeft")通过将 playersLeft 设置为活跃玩家阵数组的大小来显示开始玩家数量。
然后,在 sendPlayersToMatch() 的,在 for 循环下,类输入: playersLeft.Value = #activePlayers
function PlayerManager.sendPlayersToMatch()local availableSpawnPoints = spawnLocations:GetChildren()for playerKey, whichPlayer in Players:GetPlayers() dotable.insert(activePlayers, whichPlayer)local spawnLocation = table.remove(availableSpawnPoints, 1)preparePlayer(whichPlayer, spawnLocation)endplayersLeft.Value = #activePlayersend
显示计时器
请记住模块脚本用于中心化类似代验证码。 由于计时器在 MatchManager 中跟踪,因此使用 Timer 脚本的函数更新 TimeLeft 值。 显示管理器将听取 TimeLeft 的更改,并更新匹配到新值。
在 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()找到 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()endend使用最小玩家启动游戏。 检查状态文本是否显示:
- 正确的开始玩家数量。请记住,在未来的课程中,这个数字不会改变。
- 时间每秒钟减少,直到它停止在 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 dodisplayManager.updateStatus("Waiting for Players")repeattask.wait(gameSettings.intermissionDuration)until #Players:GetPlayers() >= gameSettings.minimumPlayersdisplayManager.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()