創建 GUI

*此內容是使用 AI(Beta 測試版)翻譯,可能含有錯誤。若要以英文檢視此頁面,請按一下這裡

目前,遊戲資訊的大部分正在輸出窗口中,對玩家來說隱形。因此,玩家可以知道遊戲中發生了什麼事,您將創建圖形用戶介面 (GUI) 並編寫代碼。

使用 GUI 顯示資訊

對於此遊戲,文字標籤將顯示當前遊戲狀態以及剩餘玩家數量和時間。

中場休息期間
>

在比賽期間
>

設置 GUI

首先,創建一個 螢幕GUI 對象來容納不同的文字元素。當玩家移動相攝影機時,畫面GUI會保持在他們屏幕上的同一位置。

為了確保所有玩家都看到相同的顯示,請將 GUI 放置在 StarterGUI 文件夾中。在遊戲啟動時,此文件夾會被複製到所有玩家。

  1. 在新手GUI文件夾中,創建一個新的螢幕GUI。然後在螢幕GUI中,新增一個名為 StatusText 的新文字標籤。

  2. 若要移動標籤,在探索器中,選擇狀態文字。然後,在遊戲視檢視中,拖動你想要的標籤。您的數字可能與視頻不同。標籤也可以使用角落上的錨點縮放。

腳本 GUI

要反映遊戲中的變更,腳本需要更新 GUI 元素。例個體、實例,遊戲狀態,是中場休息或主動回合,將被儲存在 StringValue 中,並使用本地腳本進行更新。

設定腳指令碼

狀態顯示腳本將用於在遊戲狀態變更時更新玩家的 GUI。

  1. 複製儲存 中,創建名為 DisplayValues 的文件夾。在那個文件夾中,添加一個名為狀態的 StringValue。為了稍後測試值,請給予暫時值,例如「歡迎來到戰鬥!」。

  2. 在新手GUI > 螢幕GUI > 狀態中,新增名為狀態顯示的新本地腳本。影響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. 將功能連接到已變更的事件。


    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. 伺服器儲存 > 模組腳本 中,創建一個名為 DisplayManager 的新模組腳本。重命名模組表以符合腳本名稱。

  2. 添加本地變量以追蹤中目錄:複製儲存、顯示值夾、狀態。


    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 文字標籤。作為 GUI 的第一個訊息,通過 GameManager 腳指令碼顯示中場休息的開始和結束。

  1. 伺服器腳本服務 > 遊戲管理器中,創建一個名為 displayManager 的變量,並要求伺服器儲存中的顯示管理模組。


    -- 服務
    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 true do 聲明之後的第 行,呼叫顯示管理器 > 並傳送有關等待玩家的訊息。


    -- 事件
    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"

排除故障提示

在這個時候,如果文字標籤沒有顯示第一個訊息,或仍然顯示「標籤」,請嘗試以下任一選項。

  • 請確保在狀態顯示本地腳本中,updateText() 被稱為指令碼本底部。這樣可以確保玩家獲得最新的訊息。
  • 檢查狀態字串值是否在 ReplicatedStorage 中。由於客戶端與伺服器關係的獨特性,如果它在 ServerStorage 中,本地腳本無法找到它。

顯示匹配狀態

在比相符期間,GUI會顯示兩個數字:剩餘玩家數量和時間。隨著這些數字變化,文字標籤也會變化。

設定值和功能

IntValues將用於存儲玩家數量和剩餘時間。

  1. 在 ReplicatedStorage > 顯示值中,創建兩個名為 PlayersLeft 和 TimeLeft 的 IntValue。

  2. 在 DisplayManager 中,添加變數來儲存玩家剩餘和剩餘時間值。


    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. 對於 兩個 IntValue 變量,連接 updateRoundStatus() 到變更事件。


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

顯示玩家

接下來,添加顯示遊戲開始時玩家數量的代碼。之後的課程將更新玩家左側值,因為玩家被淘汰出遊戲。

  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

顯示計時器

請記住,模組腳本用於中央化相同的代碼。因為定時器在匹配管理員中跟蹤,因此使用定時器腳指令碼的函數更新剩餘時間值。顯示管理器會聆聽 TimeLeft 的變更,並更新以符合新值。

  1. 在「配對管理員」中,創建變數以存儲 複製儲存服務 、「顯示值」文件夾和「剩餘時間」值。


    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複製並粘貼下面所有標示的整體。代碼會循環更新 timeLeft 值,直到定時器仍然活動。


    while myTimer:isRunning() do
    -- 添加 +1 可確保計時器顯示結束於 1 而不是 0。
    timeLeft.Value = (myTimer:getTimeLeft() + 1) // 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 = (myTimer:getTimeLeft() + 1) // 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

匹配管理員腳指令碼


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 = (myTimer:getTimeLeft() + 1) // 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()