ถึงเวลาที่ต้องเขียนโค้ดขั้นสุดท้ายของเกม: ทำความสะอาดและรีเซ็ตโค้ดในขั้นตอนนี้ช่วยให้แบบจำลองเกมหยุดชะงักและการแข่งขันในอนาคตเริ่มต้นเหมือนกันสำหรับผู้เล่นแต่ละคน
อัปเดต GUI
ก่อนทำการล้างและรีเซ็ต แจ้งผู้เล่นว่าเกมสิ้นสุดลงอย่างไรโดยใช้ DisplayManager เพื่อแสดงสถานะที่เหมาะสม
รับชื่อผู้ชนะ
เริ่มต้นโดยรับชื่อผู้เล่นที่ชนะถ้ามีหนึ่งก่อนหน้านี้โค้ดตรวจสอบว่าขนาดของตารางผู้เล่นที่ใช้งานลดลงเหลือ 1เพื่อรับชื่อผู้เล่นที่เหลือให้กลับชื่อในดัชนีแรกของตารางนั้น
ใน PlayerManager เริ่มฟังก์ชันโมดูลใหม่ชื่อ getWinnerName()
function PlayerManager.getWinnerName()end-- อีเวนต์Players.PlayerAdded:Connect(onPlayerJoin)เพิ่มข้อแม้ถ้าที่จะทำงานหากมีบางอย่างอยู่ใน activePlayers[1]แม้ว่าจะตรวจสอบจํานวนโต๊ะก่อนแล้ว แต่ผู้เล่นอาจถูกตัดการเชื่อมต่อหรือออกจากเกม
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เพื่อเก็บข้อความที่จะส่ง เพิ่มตัวแปรว่างเปล่าชื่อ statusToReturn
function MatchManager.prepareGame()playerManager.sendPlayersToMatch()matchStart:Fire()endfunction MatchManager.getEndStatus(endState)local statusToReturnendmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManagerตั้งค่าของ statusToReturn โดยใช้ if และ elseif สถานะตรวจสอบตัวแปรสถานะสิ้นสุด: 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 ในขณะที่ทำซ้ำจริง do ลูป, ลบ คำสั่งพิมพ์ล่าสุดจากนั้นสร้างตัวแปรชื่อ 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() กับตัวอย่างโค้ด
- หากสถานะสิ้นสุดไม่แสดง ตรวจสอบว่า 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 และค้นหาในขณะที่จริงทำซ้ำลูปดังนั้นผู้เล่นจะไม่มีอาวุธถูกลบในระหว่างช่วงพักระหว่างการแข่งขัน โทร matchManager.cleanupMatch() ก่อนที่จะเป็นครั้งสุดท้าย task.wait()
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 เพื่อทำซ้ำผ่านผู้เล่นที่ใช้งานอยู่
- ในลูปเรียก 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กลับไปที่ ผู้จัดการเกม . ในตอนท้ายของลูป 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 = (myTimer:getTimeLeft() + 1) // 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
สคริปต์ผู้จัดการผู้เล่น
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