清理和重置

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

時間來編寫遊戲的最後一個階段:清理和重置。在這個階段中的代碼確保遊戲循環到中場休息,並且每個玩家的下一場比賽都會相同。

更新控制GUI

在清理和重置之前,提醒玩家使用 DisplayManager 查看遊戲結束的狀態。

獲取勝利者的名稱

如果有一個獲勝玩家的名字,請從獲勝玩家那裡開始。 以前,代碼會檢查是否減少 1 個玩家的大小。 要取得剩餘玩家的名字,請在該表的第一個索引回歸名稱。

  1. 在 PlayerManager 中,開始名為 getWinnerName() 的新模組功能。


    function PlayerManager.getWinnerName()
    end
    -- 事件
    Players.PlayerAdded:Connect(onPlayerJoin)
  2. activePlayers[1] 中加入一個 if 語句,如果表數已在此前檢查,玩家可能已離開或退出遊戲。


    function PlayerManager.getWinnerName()
    local winningPlayer = activePlayers[1]
    if winningPlayer then
    end
    end
  3. 在 if 句中:

    • 返回玩家的名稱。
    • 對於其他,返回一個錯誤字串。

    function PlayerManager.getWinnerName()
    local winningPlayer = activePlayers[1]
    if winningPlayer then
    return winningPlayer.Name
    else
    return "Error: No winning player found"
    end
    end

取得端狀態

使用模組功能從正確的端狀態中取得資訊,無論是計時器結束或是一名玩家離開。然後,將該狀態變數傳送到 DisplayManager 以更新狀態 GUI 以正確的訊息。

  1. MatchManager 中,代碼一個名為 getEndStatus() 的新模組功能,並且以 endState 參數命名。要存儲發送的訊息,請添加名為 1> statusToReturn1> 的空變量。


    function MatchManager.prepareGame()
    playerManager.sendPlayersToMatch()
    matchStart:Fire()
    end
    function MatchManager.getEndStatus(endState)
    local statusToReturn
    end
    matchStart.Event:Connect(startTimer)
    matchEnd.Event:Connect(stopTimer)
    return MatchManager
  2. 使用 if 和 else 語句設定值 statusToReturn 的值。檢查結束狀態變量: FoundWinnerTimerUp 。為錯誤檢查包括另一個在結束。


    function MatchManager.getEndStatus(endState)
    local statusToReturn
    if endState == gameSettings.endStates.FoundWinner then
    elseif endState == gameSettings.endStates.TimerUp then
    else
    end
    end
  3. 為每個狀況添加以下內容:

    FoundWinner

    • 使用 playerManager.getWinnerName() 的變數來為贏家贏得獎勵。
    • 更新 statusToReturn 以發佈獲勝者的字串。

    TimerUp

    • 更新 statusToReturn 以發佈時間已過。

    Else

    • 更新 statusToReturn 以發生錯誤訊息,以防發生與獲取最終遊戲訊息有關的問題。

    function MatchManager.getEndStatus(endState)
    local statusToReturn
    if endState == gameSettings.endStates.FoundWinner then
    local winnerName = playerManager.getWinnerName()
    statusToReturn = "Winner is : " .. winnerName
    elseif endState == gameSettings.endStates.TimerUp then
    statusToReturn = "Time ran out!"
    else
    statusToReturn = "Error found"
    end
    end
  4. 發送回信息,輸入 return statusToReturn


    function MatchManager.getEndStatus(endState)
    local statusToReturn
    if endState == gameSettings.endStates.FoundWinner then
    local winnerName = playerManager.getWinnerName()
    statusToReturn = "Winner is : " .. winnerName
    elseif endState == gameSettings.endStates.TimerUp then
    statusToReturn = "Time ran out!"
    else
    statusToReturn = "Error found"
    end
    return statusToReturn
    end

顯示和測試

在 GameManager 中取得更新公告,並將其顯示給使用 DisplayManager 的玩家。

  1. 開啟 GameManager 。在 while 真的循環中, 刪除 最後一個 print 語句。然後,創建名為 endStatus 的變量。將它設為等於调用 matchManager.getEndStatus(endState)


    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()
    local endState = matchEnd.Event:Wait()
    local endStatus = matchManager.getEndStatus(endState)
    end
  2. 要在 GUI 標籤中顯示返回的訊息,請呼叫 displayManager.updateStatus() 並在 endStatus 中傳入。


    local endStatus = matchManager.getEndStatus(endState)
    displayManager.updateStatus(endStatus)
  3. 因此,遊戲暫停,讓玩家看到訊息,並使用 transitionTime 等待。


    local endStatus = matchManager.getEndStatus(endState)
    displayManager.updateStatus(endStatus)
    task.wait(gameSettings.transitionTime)
  4. 開始一個 測試服務器 並檢查玩家是否看到時間到達和獲勝玩家條件的訊息。

    時間到達條件
    勝利玩家狀態

排障提示

在這個時候,您無法查看訊息,請嘗試以下一項。

  • 如果您的端狀態訊息為「錯誤發現」,沒有任何條件成功。請檢查代碼在 MatchManager.getEndStatus() 對條碼示例。
  • 如果 end 狀態未顯示,請確認 task.wait(gameSettings.transitionTime) 是否在發送訊息給 displayManager 後。

開始新比賽

在開始新比相符之前,將會有一個簡短的過渡。這給玩家時間來看到最終狀態,並讓被傳送到大廳感覺更少。

在過渡結束時,剩下的玩家將被從競技場中移除,並且將重設所有代碼。這確保玩家將在下一場比賽中開始時擁有一個清潔版本的遊戲。

處理交易

當玩家移入轉換狀態時,移除他們的武器。

  1. 在 PlayerManager 中,找到本地功能。複製並貼上標示的代碼為 removePlayerWeapon() 以下。代碼會移除一個單一玩家的武器,如果它在裝備或玩家背包中啟用。


    local function removePlayerWeapon(whichPlayer)
    -- 檢查玩家是否存在,以防他們切斷或離開。
    if whichPlayer then
    local character = whichPlayer.Character
    -- 如果玩家目前在他們的角色上
    local weapon = character:FindFirstChild("Weapon")
    if weapon then
    weapon:Destroy()
    end
    -- 如果玩家有武器在他們的背包
    local backpackWeapon = whichPlayer.Backpack:FindFirstChild("Weapon")
    if backpackWeapon then
    backpackWeapon:Destroy()
    end
    else
    print("No player to remove weapon")
    end
    end
  2. 開始名為 removeAllWeapons() 的新模組功能。


    function PlayerManager.removeAllWeapons()
    end
    -- 事件
    Players.PlayerAdded:Connect(onPlayerJoin)
    return PlayerManager
  3. 在該函數中,使用 for 週期來穿過已啟用的玩家表。在週期中,呼叫 removePlayerWeapon() 並將傳入玩家。


    function PlayerManager.removeAllWeapons()
    for playerKey, whichPlayer in activePlayers do
    removePlayerWeapon(whichPlayer)
    end
    end

在比賽之間清除

清除將在MatchManager中自己的功能。 為了現在,清除會僅使用以前創建的功能來移除玩家的武器。隨著您的遊戲擴展,更多功能可以添加,例如可以重設一個地圖在相符賽中變更的功能。

  1. 開啟 MatchManager。 新增名為 cleanupMatch() 的模組功能。 在功能中,呼叫 playerManager.removeAllWeapons()


    function MatchManager.cleanupMatch()
    playerManager.removeAllWeapons()
    end
    matchStart.Event:Connect(startTimer)
    matchEnd.Event:Connect(stopTimer)
    return MatchManager
  2. 然後,呼叫清理功能。 開啟 GameManager 並找到 while 是否為 matchManager.cleanupMatch() 並在結束中場休息後,呼叫 task.wait() 之前的最後 1> Library.task.wait()1>。


    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()
    local endState = matchEnd.Event:Wait()
    local endStatus = matchManager.getEndStatus(endState)
    displayManager.updateStatus(endStatus)
    matchManager.cleanupMatch()
    task.wait(gameSettings.transitionTime)
    end
  3. 開始測試服務器並執行一場比相符。等待計時器結束,確認玩家的武器在比賽結束時被移除。

    在比賽中
    比賽結束後

重設比賽

你可能有注意到遊戲中的其他事情,例如玩家仍在競技場結束後仍在競技場中。 與比賽清理完成後,重設遊戲。 這包括將玩家傳送回競技場,並清除已啟用的玩家桌。 重設在空間置後,遊戲將能夠無限重設。

首先,啟動一個回傳玩家至大廳的函數。

  1. 在 PlayerManager:

    • 建立名為 resetPlayers() 的模組功能。
    • 添加 for 以繼續通過 activePlayers 的遊戲。
    • 在循環中,呼叫 respawnPlayerInLobby() 並將玩家作為參數傳入。

    function PlayerManager.resetPlayers()
    for playerKey, whichPlayer in activePlayers do
    respawnPlayerInLobby(whichPlayer)
    end
    end
    -- 事件
    Players.PlayerAdded:Connect(onPlayerJoin)
    return PlayerManager
  2. 請確保 activePlayers 桌子為空,以便下一場比賽,並將其設置為 {},這是一種快速的方法來重設為空桌子。


    function PlayerManager.resetPlayers()
    for playerKey, whichPlayer in activePlayers do
    respawnPlayerInLobby(whichPlayer)
    end
    activePlayers = {}
    end
  3. 開啟 MatchManager。 在 resetMatch() 的模組中輸入新的模組功能,並且呼叫 playerManager.resetPlayers() 。


    function MatchManager.resetMatch()
    playerManager.resetPlayers()
    end
    matchStart.Event:Connect(startTimer)
    matchEnd.Event:Connect(stopTimer)
    return MatchManager
  4. 回到 GameManager 。在 while 結束時,如果 true 做循環,請呼叫 matchManager.resetMatch()


    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()
    local endState = matchEnd.Event:Wait()
    local endStatus = matchManager.getEndStatus(endState)
    displayManager.updateStatus(endStatus)
    matchManager.cleanupMatch()
    task.wait(gameSettings.transitionTime)
    matchManager.resetMatch()
    end
  5. 開始測試服務器並執行一場比相符。確認您可以至少在兩個遊戲循環中執行兩次以沒有錯誤。

已完成的指令碼

下面是完成審核您的工作的指令碼。

GameManager 指令碼


-- 服務
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()
local endState = matchEnd.Event:Wait()
local endStatus = matchManager.getEndStatus(endState)
displayManager.updateStatus(endStatus)
matchManager.cleanupMatch()
task.wait(gameSettings.transitionTime)
matchManager.resetMatch()
end

MatchManager 指令碼


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 displayManager = require(moduleScripts:WaitForChild("DisplayManager"))
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 stopTimer()
myTimer:stop()
end
local function timeUp()
matchEnd:Fire(gameSettings.endStates.TimerUp)
end
local function startTimer()
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
function MatchManager.getEndStatus(endState)
local messageToReturn
if endState == gameSettings.endStates.FoundWinner then
local winnerName = playerManager.getWinnerName()
messageToReturn = "Winner is : " .. winnerName
elseif endState == gameSettings.endStates.TimerUp then
messageToReturn = "Time ran out!"
else
messageToReturn = "Error found"
end
return messageToReturn
end
function MatchManager.cleanupMatch()
playerManager.removeAllWeapons()
end
function MatchManager.resetMatch()
playerManager.resetPlayers()
end
matchStart.Event:Connect(startTimer)
matchEnd.Event:Connect(stopTimer)
return MatchManager

PlayerManager 指令碼


local PlayerManager = {}
-- 服務
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- 模組
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
-- 事件
local events = ServerStorage:WaitForChild("Events")
local matchEnd = events:WaitForChild("MatchEnd")
-- 地圖變量
local lobbySpawn = workspace.Lobby.StartSpawn
local arenaMap = workspace.Arena
local spawnLocations = arenaMap.SpawnLocations
-- 值
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local playersLeft = displayValues:WaitForChild("PlayersLeft")
-- 玩家變數
local activePlayers = {}
local playerWeapon = ServerStorage.Weapon
local function checkPlayerCount()
if #activePlayers == 1 then
matchEnd:Fire(gameSettings.endStates.FoundWinner)
print("Found winner")
end
end
local function removeActivePlayer(player)
print("removing player")
for playerKey, whichPlayer in activePlayers do
if whichPlayer == player then
table.remove(activePlayers, playerKey)
playersLeft.Value = #activePlayers
checkPlayerCount()
end
end
end
local function respawnPlayerInLobby(player)
player.RespawnLocation = lobbySpawn
player:LoadCharacter()
end
local function preparePlayer(player, whichSpawn)
player.RespawnLocation = whichSpawn
player:LoadCharacter()
local character = player.Character or player.CharacterAdded:Wait()
-- 提供工具給玩家
local sword = playerWeapon:Clone()
sword.Parent = character
local humanoid = character:WaitForChild("Humanoid")
humanoid.Died:Connect(function()
respawnPlayerInLobby(player)
removeActivePlayer(player)
end)
end
local function onPlayerJoin(player)
player.RespawnLocation = lobbySpawn
end
local function removePlayerWeapon(whichPlayer)
-- 檢查玩家是否存在,以防他們切斷或離開。
if whichPlayer then
local character = whichPlayer.Character
-- 如果玩家目前在他們的角色上
local weapon = character:FindFirstChild("Weapon")
if weapon then
weapon:Destroy()
end
-- 如果玩家有武器在他們的背包
local backpackWeapon = whichPlayer.Backpack:FindFirstChild("Weapon")
if backpackWeapon then
backpackWeapon:Destroy()
end
else
print("No player to remove weapon")
end
end
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
function PlayerManager.getWinnerName()
local winningPlayer = activePlayers[1]
if winningPlayer then
return winningPlayer.Name
else
return "Error: No player found"
end
end
function PlayerManager.removeAllWeapons()
for playerKey, whichPlayer in activePlayers do
removePlayerWeapon(whichPlayer)
end
end
function PlayerManager.resetPlayers()
for playerKey, whichPlayer in activePlayers do
respawnPlayerInLobby(whichPlayer)
end
activePlayers = {}
end
-- 事件
Players.PlayerAdded:Connect(onPlayerJoin)
return PlayerManager