ห้องสามารถจบลงได้ในเงื่อนไขบางอย่างรวมถึงเวลาที่หมดอายุหรือผู้เล่นคนเดียวที่ถูกทิ้งไว้
การจัดการผู้เล่นที่แพ้
ตอนนี้ผู้เล่นที่เอาชนะจะเกิดใหม่ในอารีน่า ตรงกัน
- ใน PlayerManager สร้างฟังก์ชันในชื่อ respawnPlayerInLobby() กำลังติดตาม:
- ตั้งค่าโครงสร้าง RespawnLocation ของผู้เล่นให้เป็นล็อบบี้Spawn
- Reload ตัวละครด้วย Player:LoadCharacter() อย่าลืม, LoadCharacter() จะสร้างผู้เล่นใหม่ที่พวกเขาสปอน, กำจัดเครื่องมือใด ๆ ที่พวกเขามี
ใช้คุณสมบัติทั่วไป
หน้าตาลึกลับใช้ได้บ่อยในสคริปต์ขั้นสูงในสถานการณ์ที่กำหนดเฉพาะ ก่อนที่จะตั้งค่าพวกเขา มีความสำคัญที่จะเข้าใจสถานการณ์ที่คุณสคริปต์อาจเผชิญ
พิจารณาสิ่งนี้: เพื่อเริกผู้เล่นที่ถูกทําลายไปยังล็อบบี้ ฟังก์ชัน respawn จะต้องเชื่อมต่อกับอีเวนต์ Died ของผู้เล่น มีปัญหาอยู่ที่นี่ หากคุณเชื่อมต่ออีเวนต
เพื่อรับชื่อผู้เล่นที่เหยียดเหตุการณ์ตาย, ใช้ฟังก์ชันอันโดยแอนได้ ฟังก์ชันอันโดยแอนไม่มีชื่อ, และสามารถสร้างได้โดยตรงภายใน Connect() แทนที่จะสร้างเป็นคู่คี่
ตัวอย่างฟังก์ชันที่ไม่ระบุชื่อด้านล่างแสดงให้เห็นภาษา
myPlayer.Died:Connect(function()
print(player)
end)
การเขียนเหตุการณ์ที่ตาย
สำหรับคุณสมบัตินี้ เมื่อตัวละครของผู้เล่นตาย พวกเขาจะเรียกใช้งานที่เรียกคืนพวกเขา
เพื่อเข้าถึงกิจกรรมของผู้เล่นที่ Died ใน 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() แล้ว, ใน 1> ภายใน</
local humanoid = character:WaitForChild("Humanoid")humanoid.Died:Connect(function()end)ในคุณสมบัติที่ไม่ระบุ, โทร respawnPlayerInLobby() . ผ่านใน player ตรงกัน
local humanoid = character:WaitForChild("Humanoid")humanoid.Died:Connect(function()respawnPlayerInLobby(player)end)เริ่มเซิร์ฟเวอร์ ตรงกันและทดสอบว่าเมื่อผู้เล่นตายพวกเขาจะเกิดใหม่ในล็อบบี้ เพื่อเอาชนะผู้เล่นให้เดินไปยังพวกเขาและใช้อาวุธของคุณจนกว่าคุณจะสามารถยืนยันได้ว่าพ
หมายเหตุ, นอกจากนี้ยังมีวิธีการทดสอบที่แตกต่างกันหากต้องการ
- เพื่อฆ่าผู้เล่นใน Server > หน้าต่างออก > บาร์คําสั่ง คัดลอกและวาง: workspace.Player1.Humanoid.Health = 0 กด Enter เพื่อดําเนินการคําสั่ง การลบผู้เล่นอื่น ๆ ใช้ Player2, Player3, etc.
- การตั้งค่า 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"}
สิ้นสุดด้วย Timer
เมื่อเวลาจะหมด ให้ยิงเหตุการณ์ "จุดสิ้นสุด" และส่งตัวแปรสถานะ "จุดสิ้นสุด" ที่ตรงกัน ด้วยวิธีนี้ สคริปต์อื่นที่ฟังสำหรับเหตุการณ์นั้นจะสามารถตอบสนองได้ตาม
ใน 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() และส่งผ่าน 1> gameSettings.endStates.TimerUp1>
-- มูลค่า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
- โมดูล GameSettings - ใช้สำหรับเข้าถึงแปรสถานะท้ายสุด
- หน้าเหตุการณ์และกิจกรรม 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() ในระบบฟังก์ชันแบบไม่ระบุที่มีการเชื่อมต่อกับอีเวนต์ Died โทร removeActivePlayer() แล้วส่งผู้เล่นเป็นตัวแปร
humanoid.Died:Connect(function()respawnPlayerInLobby(player)removeActivePlayer(player)end)เพื่อดูว่าผู้เล่นที่ชนะพบหรือไม่ เริ่มเซิร์ฟเวอร์ทดสอบ เดี่ยว เมื่อมีผู้เล่นเหลืออยู่เพียงคนเดียวคุณควรเห็น พบวิลเลียม ในหน้าต่างการออก
ปิดหมายเหตุเมื่อการแข่งขันใหม่เริ่มขึ้นในหน้าต่างการออกมีข้อผิดพลาดปรากฏขึ้น:
ข้อผิดพลาดนี้เกิดขึ้นเพราะเวลาไม่หยุด ซึ่งจะแก้ไขในส่วนถัดไป
การหยุดนับเวลา
เมื่อการแข่งขันสิ้นสุดลงด้วยผู้เล่นชนะ, เวลาจะหยุดทำงาน เพื่อหยุดเวลาให้ตรงเวลา เมื่อเวลาหมด, เวลาจะถูกหยุดให้ทำงานอีกครั้งเพื่อเริ่มต้นเวลาใหม่ นี่คือหนึ่งในข้อดีของการส
ใน MatchManager สร้างคุณสมบัติใหม่ที่มีชื่อว่า stopTimer() ภายใน ใส่ myTimer:stop() เพื่อหยุดนาฬิกา
-- สร้างวัตถุจับเวลาใหม่ที่จะใช้เพื่อติดตามเวลาการแข่งขันlocal myTimer = timer.new()-- หน้าต่างท้องถิ่นlocal function stopTimer()myTimer:stop()endlocal function timeUp()matchEnd:Fire(gameSettings.endStates.TimerUp)endเพื่อหยุดนับเวลาเมื่อการแข่งขันจบลง, เชื่อมต่อเหตุการณ์สิ้นสุดการแข่งขันไปที่ stopTimer()
-- หน้าโมดูลfunction MatchManager.prepareGame()playerManager.sendPlayersToMatch()matchStart:Fire()endmatchStart.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)
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 = (math.floor(myTimer:getTimeLeft() + 1))
-- โดยไม่ต้องตั้งเวลารอ มันจะนำเสนอการเลื่อนเวลาที่แม่นยำขึ้น
task.wait()
end
end
-- หน้าโมดูล
function MatchManager.prepareGame()
playerManager.sendPlayersToMatch()
matchStart:Fire()
end
matchStart.Event:Connect(startTimer)
matchEnd.Event:Connect(stopTimer)
return MatchManager