การจับคู่สามารถสิ้นสุดได้ในเงื่อนไขไม่กี่รายการรวมถึงตัวจับเวลาหมดหรือผู้เล่นคนเดียวถูกทอดทิ้ง
จัดการผู้เล่นที่พ่ายแพ้
ตอนนี้ผู้เล่นที่พ่ายแพ้ได้รีเช็ตตัวลงในสนาม ตรงกัน
- ใน PlayerManager สร้างฟังก์ชันท้องถิ่นชื่อ respawnPlayerInLobby() กำลังติดตาม:
- ตั้งค่าคุณสมบัติ RespawnLocation ของผู้เล่นเป็น lobbySpawn
- รีโหลดตัวละครด้วย Player:LoadCharacter() จำไว้ว่า LoadCharacter() สร้างผู้เล่นใหม่ที่จุดเกิดของพวกเขา ลบเครื่องมือใดๆ ที่พวกเขามี
ใช้ฟังก์ชันไม่ระบุตัวตน
ฟังก์ชันที่ไม่ระบุชื่อมักใช้ในสคริปต์ขั้นสูงภายใต้สถานการณ์เฉพาะก่อนที่จะกำหนดพวกเขา เป็นสิ่งสำคัญที่ต้องเข้าใจสถานการณ์ที่สคริปต์ของคุณอาจพบ
พิจารณานี้: เพื่อเทเลพอร์ตผู้เล่นที่พ่ายแพ้ไปยังล็อบบี้ ฟังก์ชันการเกิดใหม่จะต้องเชื่อมต่อกับอีเวนต์ที่ตายของผู้เล่นมีปัญหาแม้ว่าหากคุณเชื่อมต่ออีเวนต์ตามที่เรามีในอดีต ไม่มีวิธีที่จะรับชื่อผู้เล่นจากอีเวนต์ที่ตายได้สคริปต์ต้องการชื่อนั้นเพื่อลบผู้เล่นที่พ่ายแพ้ออกจากตารางติดตามผู้เล่นที่ใช้งานอยู่
เพื่อรับชื่อผู้เล่นที่กระตุ้นเหตุการณ์ตายใช้ฟังก์ชันไม่ระบุชื่อ ฟังก์ชันที่ไม่ระบุชื่อ ไม่มีชื่อและสามารถสร้างได้โดยตรงภายใน Connect() แทนที่จะแยกออกจากกัน
ฟังก์ชันที่ไม่ระบุชื่อตัวอย่างอยู่ด้านล่างที่แสดงรูปแบบ
myPlayer.Died:Connect(function()
print(player)
end)
โค้ดอีเวนต์ที่ตาย
สำหรับฟังก์ชันนี้ เมื่อตัวละครของผู้เล่นตาย พวกเขาจะกระตุ้นฟังก์ชันที่ทำให้พวกเขาเกิดใหม่
เพื่อรับการเข้าถึงอีเวนต์ที่ตายของผู้เล่นใน PlayerManager > preparePlayer() , เพิ่มตัวแปรสำหรับมนุษย์ของผู้เล่น
local function preparePlayer(player, whichSpawn)player.RespawnLocation = whichSpawnplayer:LoadCharacter()local character = player.Character or player.CharacterAdded:Wait()local sword = playerWeapon:Clone()sword.Parent = characterlocal humanoid = character:WaitForChild("Humanoid")endสร้างฟังก์ชันที่ไม่ระบุชื่อที่เชื่อมต่อกับอีเวนต์ Diedเริ่มต้นโดยพิมพ์ humanoid.Died:Connect() .จากนั้น, ภายใน Connect() , ประเภท function() , กด Enter เพื่อเสร็จสิ้นอัตโนมัติ end และลบเครื่องหมายวรรคที่เหลือ
local humanoid = character:WaitForChild("Humanoid")humanoid.Died:Connect(function()end)ในฟังก์ชันที่ไม่ระบุชื่อ โทร respawnPlayerInLobby() . ส่งใน player , ตรงกัน
local humanoid = character:WaitForChild("Humanoid")humanoid.Died:Connect(function()respawnPlayerInLobby(player)end)เริ่มต้นเซิร์ฟเวอร์ ตรงกันพวกเขาจะเกิดใหม่ในล็อบบี้เพื่อเอาชนะผู้เล่น, เดินไปหาพวกเขาและใช้อาวุธของคุณจนกว่าคุณจะยืนยันได้ว่าพวกเขาได้เกิดใหม่ในล็อบบี้
โจมตีผู้เล่นที่ 2Player2 ในล็อบบี้หลังจากเกิดใหม่
โปรดทราบว่ามีวิธีทดสอบที่แตกต่างกันบางวิธีหากต้องการ
- เพื่อฆ่าผู้เล่นใน Server > Output window > Command Bar ให้คัดลอกและวาง: workspace.Player1.Humanoid.Health = 0กด Enter เพื่อรันคำสั่งเพื่อลบผู้เล่นคนอื่นใช้ Player2, Player3, ฯลฯ
- การตั้งค่า GameSettings > matchDuration เป็นเวลานานขึ้นสามารถให้เวลามากขึ้นในการค้นหาและนำผู้เล่นทั้งหมดออก
- เพื่อมีการทดสอบที่รวดเร็วขึ้น เปลี่ยน GameSettings > minimumPlayers เป็นตัวเลขที่เล็กกว่า เช่น 2
จบเกม
ตอนนี้ที่ผู้เล่นที่พ่ายแพ้ได้เกิดใหม่แล้ว เริ่มทำงานเพื่อสิ้นสุดเกมจำได้ไหมที่สร้างเหตุการณ์ MatchEnd? มันจะถูกยิงเมื่อเวลาหมดลงหรือพบผู้ชนะ
เพื่อบอกสคริปต์อื่นที่เงื่อนไขสิ้นสุดเกม สร้างตารางด้วยตัวแปรสำหรับ TimerUp และ FoundWinnerเมื่ออีเวนต์การแข่งขันสิ้นสุด จะส่งในตัวแปรเพื่อให้สคริปต์อื่นๆ ตอบสนองได้
ใน GameSettings สร้างตารางโมดูลว่างชื่อ endStates
local GameSettings = {}-- ตัวแปรเกมGameSettings.intermissionDuration = 5GameSettings.matchDuration = 10GameSettings.minimumPlayers = 2GameSettings.transitionTime = 5-- ปิดGameSettings.endStates = {}return GameSettingsสร้างตัวแปรสองตัวที่ชื่อ TimerUp และ FoundWinner ตั้งค่าแต่ละอย่างเป็นสตริงที่ตรงกับชื่อของพวกเขา สตริงเหล่านี้จะถูกใช้เพื่อทดสอบโค้ด
GameSettings.endStates = {TimerUp = "TimerUp",FoundWinner = "FoundWinner"}
สิ้นสุดด้วยตัวจับเวลา
เมื่อเวลาจบลง ส่งเหตุการณ์จบการแข่งขันและส่งตัวแปรสถานะจบที่ตรงกันทางนั้น สคริปต์อื่นที่ฟังเหตุการณ์นั้นสามารถตอบสนองได้ตามนั้นโปรดจำไว้ว่าในขณะที่อีเวนต์ส่งสัญญาณไฟ คุณยังสามารถส่งข้อมูลที่ได้รับจากการฟังสคริปต์ เช่น TimerUp หรือ FoundWinner
ใน GameManager , ในขณะที่ทำซ้ำจนกว่าจะเป็นจริง ค้นหาบรรทัด matchEnd.Event:Wait() . ที่จุดเริ่มต้นของบรรทัด เพิ่ม local 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()endเพื่อยืนยันว่าได้รับสถานะที่ถูกต้องแล้ว เพิ่มคำสั่งพิมพ์รวมถึง 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()print("Game ended with: " .. endState)endใน MatchManager ค้นหา timeUp() และ ลบ คำสั่งพิมพ์จากนั้น, เพื่อยิงอีเวนต์สิ้นสุดการแข่งขัน, พิมพ์ matchEnd:Fire() และส่งใน gameSettings.endStates.TimerUp
-- ค่าlocal displayValues = ReplicatedStorage:WaitForChild("DisplayValues")local timeLeft = displayValues:WaitForChild("TimeLeft")-- สร้างวัตถุนาฬิกาใหม่ที่จะใช้เพื่อติดตามเวลาการแข่งขันlocal myTimer = timer.new()-- ฟังก์ชันท้องถิ่นlocal function timeUp()matchEnd:Fire(gameSettings.endStates.TimerUp)endตรงกันเมื่อเวลาหมดลงแล้วตรวจสอบว่าคำสั่งพิมพ์รวมถึงสตริงที่เก็บไว้ในตัวแปร TimerUp หรือไม่
เคล็ดลับการแก้ปัญหา
ในจุดนี้ข้อความไม่ได้แสดงขึ้น ลองหนึ่งในสิ่งต่อไปนี้
- ตรวจสอบว่าทุกที่ที่แปรสถานะสิ้นสุดถูกเรียก พวกเขาจะถูกเขียนอย่างถูกต้องเช่นที่นี่: gameSettings.endStates.TimerUp
- ตรวจสอบให้ใช้: (ตัวประกอบคอลอน) กับ แทนที่จุลภาคของจุลภาค, เช่นใน
ตรงกัน
ต่อไป สคริปต์จะต้องระบุผู้เล่นที่ชนะ ลบผู้เล่นที่แพ้ และดำเนินการทำความสะอาดเช่นหยุดเวลานับถอยหลังการจับคู่จะสิ้นสุดลงเช่นกันหากผู้เล่นคนหนึ่งถูกทอดทิ้งเพื่อดูว่าเงื่อนไข FoundWinner ถูกต้องหรือไม่ ตรงกัน
ตรวจสอบจํานวนผู้เล่น
การจับคู่จะสิ้นสุดลงหากเหลือผู้เล่นเพียงคนเดียวเพื่อตรวจสอบนี้ สคริปต์จะต้องติดตามผู้เล่นในรอบเมื่อผู้เล่นคนหนึ่งถูกทอดทิ้งแล้ว สามารถกำหนดผู้ชนะได้
ใน PlayerManager กำหนดตัวแปรต่อไปนี้:
- ไดเรกทอรี ModuleScripts
- โมดูลการตั้งค่าเกม - ใช้เพื่อเข้าถึงตัวแปรสถานะสุดท้าย
- โฟลเดอร์กิจกรรมและอีเวนต์ MatchEnd - เหตุการณ์ไฟ
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")เหนือ respawnPlayerInLobby() , เพิ่มฟังก์ชันท้องถิ่นใหม่ชื่อ checkPlayerCount() .
-- ตัวแปรผู้เล่นlocal activePlayers = {}local playerWeapon = ServerStorage.Weaponlocal function checkPlayerCount()endlocal function respawnPlayerInLobby(player)ภายในฟังก์ชันนั้นใช้คำสั่ง if จากนั้นเพื่อตรวจสอบผู้ชนะ ในคำสั่งนั้น:
- ตรวจสอบว่าขนาดของตาราง activePlayers มีขนาด 1 หรือไม่
- หากเป็นเช่นนั้นให้ยิง matchEnd และส่งใน gameSettings.endStates.FoundWinner
local function checkPlayerCount()if #activePlayers == 1 thenmatchEnd:Fire(gameSettings.endStates.FoundWinner)endend
ลบผู้เล่น
ไม่สามารถเก็บจํานวนที่แม่นยําได้หากผู้เล่นถูกลบออกเมื่อผู้เล่นถูกเอาชนะ ให้เก็บจํานวนผู้เล่นที่ถูกต้องโดยการลบพวกเขาออกจากตารางผู้เล่นจากนั้นตรวจสอบขนาดของตารางผู้เล่นที่ใช้งานเพื่อดูว่ามีผู้ชนะหรือไม่
ภายใต้ checkPlayerCount() , สร้างฟังก์ชันท้องถิ่นใหม่ชื่อ removeActivePlayer() ด้วยพารามิเตอร์ชื่อ player
local function checkPlayerCount()if #activePlayers == 1 thenmatchEnd:Fire(gameSettings.endStates.FoundWinner)endendlocal function removeActivePlayer(player)endเพื่อค้นหาผู้เล่นในตาราง activePlayers ให้ทำซ้ำโดยใช้ลูป forจากนั้นเพิ่มคำสั่ง if ที่จะทำงานหากผู้เล่นที่ตรงกับชื่อผ่านเข้าสู่ฟังก์ชันถูกพบ
local function removeActivePlayer(player)for playerKey, whichPlayer in activePlayers doif whichPlayer == player thenendendendเพื่อลบผู้เล่นในข้อความ if:
- โทร table.remove() . ภายในเครื่องหมายวรรคที่สอง, ส่งใน activePlayers , ตารางที่จะดู, และ playerKey - ผู้เล่นที่จะลบออกจากตาราง
- ตั้งค่ามูลค่าของวัตถุ playersLeft เป็น #activePlayers .
- ตรวจสอบผู้เล่นที่ชนะโดยการเรียกใช้ checkPlayerCount()
local function removeActivePlayer(player)for playerKey, whichPlayer in activePlayers doif whichPlayer == player thentable.remove(activePlayers, playerKey)playersLeft.Value = #activePlayerscheckPlayerCount()endendend
เชื่อมต่อเหตุการณ์และทดสอบ
เพื่อใช้ฟังก์ชันที่เพิ่งสร้างขึ้นใหม่ โทรจากภายในฟังก์ชันที่ไม่ระบุชื่อที่เชื่อมโยงกับเหตุการณ์ Died ของผู้เล่น
ค้นหา preparePlayer() . ในฟังก์ชันที่ไม่ระบุชื่อด้วยการเชื่อมต่ออีเวนต์ตาย โทร removeActivePlayer() . จากนั้นส่งผู้เล่นในฐานะพารามิเตอร์
humanoid.Died:Connect(function()respawnPlayerInLobby(player)removeActivePlayer(player)end)เพื่อดูว่าผู้เล่นที่ชนะถูกพบหรือไม่ เริ่มต้นเซิร์ฟเวอร์ทดสอบ **** เมื่อเหลือผู้เล่นเพียงคนเดียวคุณควรเห็น FoundWinner ในหน้าต่างผลลัพธ์
ปิดสังเกตเมื่อการแข่งขันใหม่เริ่มต้น ข้อผิดพลาดปรากฏในหน้าต่างเอาต์พุต:
ข้อผิดพลาดนี้เกิดจากนักจับเวลาไม่ถูกหยุด ซึ่งจะถูกแก้ไขในส่วนถัดไป
หยุดนาฬิกาจับเวลา
ทุกครั้งที่การแข่งขันสิ้นสุดลงด้วยผู้เล่นที่ชนะ เวลาจะหยุดเช่นกันเพื่อหยุดนาฬิกาก่อนที่เวลาจะหมดลง ให้นาฬิกาหยุดทุกครั้งที่เหตุการณ์จบการแข่งขันเกิดขึ้นนี่เป็นหนึ่งในประโยชน์ของการสร้างอีเวนต์พวกเขาสามารถนำกลับมาใช้ในหลายสถานการณ์เพื่อสร้างความสัมพันธ์ระหว่างสาเหตุและผล
ใน MatchManager สร้างฟังก์ชันท้องถิ่นใหม่ชื่อ stopTimer() ภายในพิมพ์ myTimer:stop() เพื่อหยุดเวลานับถอยหลัง
-- สร้างวัตถุนาฬิกาใหม่ที่จะใช้เพื่อติดตามเวลาการแข่งขันlocal myTimer = timer.new()-- ฟังก์ชันท้องถิ่นlocal function stopTimer()myTimer:stop()endlocal function timeUp()matchEnd:Fire(gameSettings.endStates.TimerUp)endเพื่อหยุดนาฬิกาเมื่อการแข่งขันสิ้นสุด เชื่อมต่ออีเวนต์ matchEnd กับ stopTimer()
-- ฟังก์ชันของโมดูลfunction MatchManager.prepareGame()playerManager.sendPlayersToMatch()matchStart:Fire()endmatchStart.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)
end
end
local function removeActivePlayer(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 onPlayerJoin(player)
player.RespawnLocation = lobbySpawn
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
-- ฟังก์ชันของโมดูล
function PlayerManager.sendPlayersToMatch()
local arenaSpawns = spawnLocations:GetChildren()
for playerKey, whichPlayer in Players:GetPlayers() do
table.insert(activePlayers, whichPlayer)
local spawnLocation = table.remove(arenaSpawns, 1)
preparePlayer(whichPlayer, spawnLocation)
end
playersLeft.Value = #activePlayers
end
-- อีเวนต์
Players.PlayerAdded:Connect(onPlayerJoin)
return PlayerManager
สคริปต์ GameSettings
local GameSettings = {}-- ตัวแปรเกมGameSettings.intermissionDuration = 5GameSettings.matchDuration = 10GameSettings.minimumPlayers = 2GameSettings.transitionTime = 5-- ปิดGameSettings.endStates = {TimerUp = "TimerUp",FoundWinner = "FoundWinner"}return GameSettings
สคริปต์ 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()print("Game ended with: " .. endState)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 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()
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)
matchEnd.Event:Connect(stopTimer)
return MatchManager