時間來編寫遊戲的最後一個階段:清理和重置。在這個階段中的代碼確保遊戲循環到中場休息,並且每個玩家的下一場比賽都會相同。
更新控制GUI
在清理和重置之前,提醒玩家使用 DisplayManager 查看遊戲結束的狀態。
獲取勝利者的名稱
如果有一個獲勝玩家的名字,請從獲勝玩家那裡開始。 以前,代碼會檢查是否減少 1 個玩家的大小。 要取得剩餘玩家的名字,請在該表的第一個索引回歸名稱。
在 PlayerManager 中,開始名為 getWinnerName() 的新模組功能。
function PlayerManager.getWinnerName()end-- 事件Players.PlayerAdded:Connect(onPlayerJoin)在 activePlayers[1] 中加入一個 if 語句,如果表數已在此前檢查,玩家可能已離開或退出遊戲。
function PlayerManager.getWinnerName()local winningPlayer = activePlayers[1]if winningPlayer thenendend在 if 句中:
- 返回玩家的名稱。
- 對於其他,返回一個錯誤字串。
function PlayerManager.getWinnerName()local winningPlayer = activePlayers[1]if winningPlayer thenreturn winningPlayer.Nameelsereturn "Error: No winning player found"endend
取得端狀態
使用模組功能從正確的端狀態中取得資訊,無論是計時器結束或是一名玩家離開。然後,將該狀態變數傳送到 DisplayManager 以更新狀態 GUI 以正確的訊息。
在 MatchManager 中,代碼一個名為 getEndStatus() 的新模組功能,並且以 endState 參數命名。要存儲發送的訊息,請添加名為 1> statusToReturn1> 的空變量。
function MatchManager.prepareGame()playerManager.sendPlayersToMatch()matchStart:Fire()endfunction MatchManager.getEndStatus(endState)local statusToReturnendmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManager使用 if 和 else 語句設定值 statusToReturn 的值。檢查結束狀態變量: FoundWinner 和 TimerUp 。為錯誤檢查包括另一個在結束。
function MatchManager.getEndStatus(endState)local statusToReturnif endState == gameSettings.endStates.FoundWinner thenelseif endState == gameSettings.endStates.TimerUp thenelseendend為每個狀況添加以下內容:
FoundWinner
- 使用 playerManager.getWinnerName() 的變數來為贏家贏得獎勵。
- 更新 statusToReturn 以發佈獲勝者的字串。
TimerUp
- 更新 statusToReturn 以發佈時間已過。
Else
- 更新 statusToReturn 以發生錯誤訊息,以防發生與獲取最終遊戲訊息有關的問題。
function MatchManager.getEndStatus(endState)local statusToReturnif endState == gameSettings.endStates.FoundWinner thenlocal winnerName = playerManager.getWinnerName()statusToReturn = "Winner is : " .. winnerNameelseif endState == gameSettings.endStates.TimerUp thenstatusToReturn = "Time ran out!"elsestatusToReturn = "Error found"endend發送回信息,輸入 return statusToReturn 。
function MatchManager.getEndStatus(endState)local statusToReturnif endState == gameSettings.endStates.FoundWinner thenlocal winnerName = playerManager.getWinnerName()statusToReturn = "Winner is : " .. winnerNameelseif endState == gameSettings.endStates.TimerUp thenstatusToReturn = "Time ran out!"elsestatusToReturn = "Error found"endreturn statusToReturnend
顯示和測試
在 GameManager 中取得更新公告,並將其顯示給使用 DisplayManager 的玩家。
開啟 GameManager 。在 while 真的循環中, 刪除 最後一個 print 語句。然後,創建名為 endStatus 的變量。將它設為等於调用 matchManager.getEndStatus(endState) 。
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()local endState = matchEnd.Event:Wait()local endStatus = matchManager.getEndStatus(endState)end要在 GUI 標籤中顯示返回的訊息,請呼叫 displayManager.updateStatus() 並在 endStatus 中傳入。
local endStatus = matchManager.getEndStatus(endState)displayManager.updateStatus(endStatus)因此,遊戲暫停,讓玩家看到訊息,並使用 transitionTime 等待。
local endStatus = matchManager.getEndStatus(endState)displayManager.updateStatus(endStatus)task.wait(gameSettings.transitionTime)開始一個 測試服務器 並檢查玩家是否看到時間到達和獲勝玩家條件的訊息。
排障提示
在這個時候,您無法查看訊息,請嘗試以下一項。
- 如果您的端狀態訊息為「錯誤發現」,沒有任何條件成功。請檢查代碼在 MatchManager.getEndStatus() 對條碼示例。
- 如果 end 狀態未顯示,請確認 task.wait(gameSettings.transitionTime) 是否在發送訊息給 displayManager 後。
開始新比賽
在開始新比相符之前,將會有一個簡短的過渡。這給玩家時間來看到最終狀態,並讓被傳送到大廳感覺更少。
在過渡結束時,剩下的玩家將被從競技場中移除,並且將重設所有代碼。這確保玩家將在下一場比賽中開始時擁有一個清潔版本的遊戲。
處理交易
當玩家移入轉換狀態時,移除他們的武器。
在 PlayerManager 中,找到本地功能。複製並貼上標示的代碼為 removePlayerWeapon() 以下。代碼會移除一個單一玩家的武器,如果它在裝備或玩家背包中啟用。
local function removePlayerWeapon(whichPlayer)-- 檢查玩家是否存在,以防他們切斷或離開。if whichPlayer thenlocal character = whichPlayer.Character-- 如果玩家目前在他們的角色上local weapon = character:FindFirstChild("Weapon")if weapon thenweapon:Destroy()end-- 如果玩家有武器在他們的背包local backpackWeapon = whichPlayer.Backpack:FindFirstChild("Weapon")if backpackWeapon thenbackpackWeapon:Destroy()endelseprint("No player to remove weapon")endend開始名為 removeAllWeapons() 的新模組功能。
function PlayerManager.removeAllWeapons()end-- 事件Players.PlayerAdded:Connect(onPlayerJoin)return PlayerManager在該函數中,使用 for 週期來穿過已啟用的玩家表。在週期中,呼叫 removePlayerWeapon() 並將傳入玩家。
function PlayerManager.removeAllWeapons()for playerKey, whichPlayer in activePlayers doremovePlayerWeapon(whichPlayer)endend
在比賽之間清除
清除將在MatchManager中自己的功能。 為了現在,清除會僅使用以前創建的功能來移除玩家的武器。隨著您的遊戲擴展,更多功能可以添加,例如可以重設一個地圖在相符賽中變更的功能。
開啟 MatchManager。 新增名為 cleanupMatch() 的模組功能。 在功能中,呼叫 playerManager.removeAllWeapons() 。
function MatchManager.cleanupMatch()playerManager.removeAllWeapons()endmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManager然後,呼叫清理功能。 開啟 GameManager 並找到 while 是否為 matchManager.cleanupMatch() 並在結束中場休息後,呼叫 task.wait() 之前的最後 1> Library.task.wait()1>。
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()local endState = matchEnd.Event:Wait()local endStatus = matchManager.getEndStatus(endState)displayManager.updateStatus(endStatus)matchManager.cleanupMatch()task.wait(gameSettings.transitionTime)end開始測試服務器並執行一場比相符。等待計時器結束,確認玩家的武器在比賽結束時被移除。
重設比賽
你可能有注意到遊戲中的其他事情,例如玩家仍在競技場結束後仍在競技場中。 與比賽清理完成後,重設遊戲。 這包括將玩家傳送回競技場,並清除已啟用的玩家桌。 重設在空間置後,遊戲將能夠無限重設。
首先,啟動一個回傳玩家至大廳的函數。
在 PlayerManager:
- 建立名為 resetPlayers() 的模組功能。
- 添加 for 以繼續通過 activePlayers 的遊戲。
- 在循環中,呼叫 respawnPlayerInLobby() 並將玩家作為參數傳入。
function PlayerManager.resetPlayers()for playerKey, whichPlayer in activePlayers dorespawnPlayerInLobby(whichPlayer)endend-- 事件Players.PlayerAdded:Connect(onPlayerJoin)return PlayerManager請確保 activePlayers 桌子為空,以便下一場比賽,並將其設置為 {},這是一種快速的方法來重設為空桌子。
function PlayerManager.resetPlayers()for playerKey, whichPlayer in activePlayers dorespawnPlayerInLobby(whichPlayer)endactivePlayers = {}end開啟 MatchManager。 在 resetMatch() 的模組中輸入新的模組功能,並且呼叫 playerManager.resetPlayers() 。
function MatchManager.resetMatch()playerManager.resetPlayers()endmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManager回到 GameManager 。在 while 結束時,如果 true 做循環,請呼叫 matchManager.resetMatch() 。
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()local endState = matchEnd.Event:Wait()local endStatus = matchManager.getEndStatus(endState)displayManager.updateStatus(endStatus)matchManager.cleanupMatch()task.wait(gameSettings.transitionTime)matchManager.resetMatch()end開始測試服務器並執行一場比相符。確認您可以至少在兩個遊戲循環中執行兩次以沒有錯誤。
已完成的指令碼
下面是完成審核您的工作的指令碼。
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 dodisplayManager.updateStatus("Waiting for Players")repeattask.wait(gameSettings.intermissionDuration)until #Players:GetPlayers() >= gameSettings.minimumPlayersdisplayManager.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