Kết thúc trận đấu

*Nội dung này được dịch bằng AI (Beta) và có thể có lỗi. Để xem trang này bằng tiếng Anh, hãy nhấp vào đây.

Các trận đấu có thể kết thúc trong một vài điều kiện bao gồm thời gian chạy hết hoặc một người chơi duy nhất bị bỏ lại.

Quản lý người chơi bị thất bại

Hiện tại, những người chơi bị đánh bại đã hồi sinh trong đấu trường. Thay vào đó, gửi họ trở lại sảnh đợi để chờ tương thíchtiếp theo.

  1. Trong PlayerManager, tạo một chức năng địa phương có tên respawnPlayerInLobby(). Trong chức năng đó, thực hiện những điều theo dõi:
  • Đặt tính năng RespawnLocation của người chơi vào lobbySpawn.
  • Tải lại nhân vật với Player:LoadCharacter() . Hãy nhớ, LoadCharacter() tạo lại người chơi tại spawn của họ, loại bỏ bất kỳ công cụ nào họ có.

Sử dụng chức năng vô danh

Chức năng vô danh thường được sử dụng trong các kịch bản nâng cao dưới các tình huống cụ thể.Trước khi xác định chúng, quan trọng là hiểu một tình huống mà kịch bản của bạn có thể gặp phải.

Hãy xem xét điều này: Để dịch chuyển người chơi bị thất bại vào sảnh, chức năng hồi sinh sẽ phải được kết nối với sự kiện Chết của người chơi.Tuy nhiên, có một vấn đề.Nếu bạn kết nối sự kiện như chúng tôi đã có trong quá khứ, không có cách nào để lấy tên của người chơi từ sự kiện Chết.Tập lệnh cần tên đó để loại bỏ một người chơi bị thất bại khỏi bảng theo dõi các người chơi chủ động.

Để lấy tên của người chơi đã kích hoạt sự kiện Chết, hãy sử dụng chức năng vô danh. Chức năng vô danh không có tên, và có thể được tạo trực tiếp trong Connect() thay vì riêng biệt.

Một chức năng vô danh mẫu được hiển thị dưới đây cho thấy ngữ pháp.


myPlayer.Died:Connect(function()
print(player)
end)

Mã sự kiện chết

Đối với chức năng này, mỗi khi nhân vật của một người chơi chết, họ sẽ kích hoạt chức năng tái sinh chúng.

  1. Để truy cập sự kiện Chết của người chơi, trong PlayerManager > preparePlayer(), thêm một biến cho hình người của người chơi.


    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")
    end
  2. Tạo một chức năng vô danh kết nối với sự kiện Chết.Bắt đầu bằng cách gõ humanoid.Died:Connect() .Sau đó, bên trong Connect() , nhập function() , nhấn Enter để hoàn thành tự động end , và xóa dấu ngoặc kép dư.


    local humanoid = character:WaitForChild("Humanoid")
    humanoid.Died:Connect(function()
    end)
  3. Trong chức năng vô danh, gọi respawnPlayerInLobby() . Truyền player , một biến lưu trữ người chơi đang chuẩn bị bước vào một tương thích.


    local humanoid = character:WaitForChild("Humanoid")
    humanoid.Died:Connect(function()
    respawnPlayerInLobby(player)
    end)
  4. Bắt đầu một máy chủ và chơi một tương thích.Kiểm tra khi một người chơi chết, họ sẽ hồi sinh trong sảnh.Để đánh bại người chơi, đi đến họ và sử dụng vũ khí của bạn cho đến khi bạn có thể xác nhận họ đã hồi sinh trong sảnh đợi.

    Tấn công Player2
    Người chơi 2 trong Sảnh sau khi hồi sinh

Lưu ý, cũng có một số cách thử nghiệm khác nếu cần.

  • Để giết một người chơi, trong cửa sổ Server > Output > Command Bar, sao chép và dán: workspace.Player1.Humanoid.Health = 0 .Nhấn Enter để chạy lệnh.Để loại bỏ người chơi khác, hãy sử dụng Player2, Player3, v.v.
  • Bột cài đặt trò chơi > matchDuration đặt thời gian lâu hơn có thể cho bạn thêm thời gian để tìm và lấy tất cả người chơi.
  • Để có những bài kiểm tra nhanh hơn, thay đổi GameSettings > minimumPlayers thành số nhỏ hơn, như 2.

Kết thúc trò chơi

Bây giờ khi những người chơi bị thất bại đã hồi sinh, bắt đầu làm việc để kết thúc trò chơi.Nhớ tạo sự kiện MatchEnd? Nó sẽ bị kích hoạt khi hết thời gian hoặc tìm thấy người chiến thắng.

Để cho các kịch bản khác biết điều kiện nào đã kết thúc trò chơi, tạo một bảng với các biến cho TimerUpFoundWinner .Khi sự kiện kết thúc trận đấu xảy ra, nó sẽ truyền qua một biến để các kịch bản khác có thể đáp lại.

  1. Trong GameSettings, tạo một bảng module trống có tên là endStates.


    local GameSettings = {}
    -- Biến trò chơi
    GameSettings.intermissionDuration = 5
    GameSettings.matchDuration = 10
    GameSettings.minimumPlayers = 2
    GameSettings.transitionTime = 5
    -- Các cách có thể kết thúc trò chơi.
    GameSettings.endStates = {
    }
    return GameSettings
  2. Tạo hai biến có tên là TimerUpFoundWinner. Đặt mỗi cái thành một chuỗi phù hợp với tên của chúng. Những chuỗi này sẽ được sử dụng để kiểm tra mã.


GameSettings.endStates = {
TimerUp = "TimerUp",
FoundWinner = "FoundWinner"
}

Kết thúc với một bộ đếm thời gian

Khi hết thời gian, kích hoạt sự kiện Kết thúc trận đấu và gửi biến trạng thái kết thúc phù hợp.Theo cách đó, các kịch bản khác lắng nghe sự kiện đó có thể đáp lại tương ứng.Hãy nhớ rằng trong khi sự kiện phát tín hiệu, cũng có thể gửi dữ liệu được nhận bởi các kịch bản lắng nghe, như TimerUp hoặc FoundWinner .

  1. Trong GameManager , trong vòng lặp while true, tìm dòng matchEnd.Event:Wait() . Ở đầu dòng, thêm local 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()
    end
  2. Để xác nhận rằng trạng thái chính xác đã được nhận, hãy thêm một tuyên bố in bao gồm 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()
    print("Game ended with: " .. endState)
    end
  3. Trong MatchManager, tìm timeUp()xóa tuyên bố in.Sau đó, để kích hoạt sự kiện kết thúc trận đấu, hãy nhập matchEnd:Fire() và truyền gameSettings.endStates.TimerUp .


    -- Giá trị
    local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
    local timeLeft = displayValues:WaitForChild("TimeLeft")
    -- Tạo một đối tượng hẹn giờ mới để được sử dụng để theo dõi thời gian trận đấu.
    local myTimer = timer.new()
    -- Chức năng địa phương
    local function timeUp()
    matchEnd:Fire(gameSettings.endStates.TimerUp)
    end
  4. Kiểm tra một tương thích. Khi hết thời gian, hãy kiểm tra xem tuyên bố in bao gồm chuỗi được lưu trong biến TimerUp.

Mẹo khắc phục sự cố

Tại thời điểm này, tin nhắn không được hiển thị, hãy thử một trong những điều sau.

  • Kiểm tra rằng bất cứ nơi nào biến trạng thái cuối được gọi, chúng được viết chính xác, giống như ở đây: gameSettings.endStates.TimerUp .
  • Hãy chắc chắn sử dụng : (operator dấu phân cách) với thay vì operator chấm tròn, giống như trong .

Mã một trận chiến tương thích

Tiếp theo, kịch bản cần xác định người chơi chiến thắng, loại bỏ người chơi thua cuộc và chạy dọn dẹp như dừng bộ đếm thời gian.Các trận đấu cũng sẽ kết thúc nếu một người chơi bị bỏ lại.Để xem nếu điều kiện FoundWinner được đáp ứng, bạn sẽ cần một chức năng kiểm tra số còn lại trong bảng theo dõi người chơi trong một tương thích.

Kiểm tra số lượng người chơi

Các trận đấu sẽ kết thúc nếu chỉ còn một người chơi.Để kiểm tra điều này, kịch bản cần theo dõi người chơi trong một vòng.Khi một người chơi đã rời đi, một người chiến thắng có thể được gán.

  1. Trong PlayerManager, xác định các biến sau:

    • Thư mục ModuleScripts
    • Module GameSettings - Được sử dụng để truy cập các biến trạng thái cuối cùng
    • Thư mục sự kiện và sự kiện MatchEnd - Xảy ra sự kiện

    local PlayerManager = {}
    -- Dịch vụ
    local Players = game:GetService("Players")
    local ServerStorage = game:GetService("ServerStorage")
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    -- Mô-đun
    local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
    local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
    -- Sự kiện
    local events = ServerStorage:WaitForChild("Events")
    local matchEnd = events:WaitForChild("MatchEnd")
  2. Trên respawnPlayerInLobby(), thêm một chức năng địa phương mới có tên là checkPlayerCount().


    -- Biến người chơi
    local activePlayers = {}
    local playerWeapon = ServerStorage.Weapon
    local function checkPlayerCount()
    end
    local function respawnPlayerInLobby(player)
  3. Trong chức năng đó, sử dụng một if then câu để kiểm tra một người chiến thắng. Trong câu đó:

    • Kiểm tra xem kích thước của bảng activePlayers có là 1 không.
    • Nếu vậy, bắn matchEnd và truyền gameSettings.endStates.FoundWinner .

    local function checkPlayerCount()
    if #activePlayers == 1 then
    matchEnd:Fire(gameSettings.endStates.FoundWinner)
    end
    end

Loại bỏ một người chơi

Một số đếm chính xác không thể được giữ nếu người chơi không bị xóa.Khi một người chơi bị đánh bại, giữ một số lượng người chơi chính xác bằng cách loại bỏ họ khỏi bảng người chơi.Sau đó, kiểm tra kích thước bảng người chơi hoạt động để xem có người chiến thắng không.

  1. Dưới checkPlayerCount(), tạo một chức năng địa phương mới có tên removeActivePlayer() với một tham số có tên player .


    local function checkPlayerCount()
    if #activePlayers == 1 then
    matchEnd:Fire(gameSettings.endStates.FoundWinner)
    end
    end
    local function removeActivePlayer(player)
    end
  2. Để tìm người chơi trong bảng activePlayers, lặp lại qua nó bằng một vòng lặp for.Sau đó, thêm một tuyên bố if chạy nếu một người chơi phù hợp với tên được chuyển vào chức năng được tìm thấy.


    local function removeActivePlayer(player)
    for playerKey, whichPlayer in activePlayers do
    if whichPlayer == player then
    end
    end
    end
  3. Để xóa người chơi, trong if tuyên bố:

    • Gọi table.remove() . Bên trong dấu ngoặc, truyền activePlayers , bảng để xem, và playerKey - người chơi để xóa khỏi bảng.
    • Đặt giá trị của đối tượng playersLeft thành #activePlayers.
    • Kiểm tra một người chơi chiến thắng bằng cách chạy checkPlayerCount() .

    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

Kết nối sự kiện và thử nghiệm

Để sử dụng chức năng vừa tạo, gọi nó từ bên trong chức năng ẩn được kết nối với sự kiện Died của người chơi.

  1. Tìm preparePlayer() . Trong chức năng vô danh với kết nối sự kiện Chết, gọi removeActivePlayer() . Sau đó, chuyển người chơi làm tham số.


    humanoid.Died:Connect(function()
    respawnPlayerInLobby(player)
    removeActivePlayer(player)
    end)
  2. Để xem có người chơi chiến thắng được tìm thấy hay không, hãy khởi động một máy chủ thử nghiệm test server .Khi chỉ còn một người chơi, bạn nên thấy FoundWinner trong cửa sổ Thành phẩm.

  3. Tiếp tục kiểm tra và để trận đấu kết thúc. Nhận thấy khi một trận đấu mới bắt đầu, một lỗi xuất hiện trong cửa sổ Thành phẩm:

Lỗi này xảy ra vì thời gian chờ không bị ngừng, điều này sẽ được sửa chữa trong phần tiếp theo.

Dừng hẹn giờ

Mỗi khi một trận đấu kết thúc với một người chơi chiến thắng, bộ đếm thời gian cũng nên dừng lại.Để ngăn chặn bộ đếm thời gian trước khi hết thời gian, hãy cho bộ đếm thời gian dừng lại mỗi khi sự kiện kết thúc trận đấu xảy ra.Đây là một trong những lợi ích của việc tạo sự kiện.Chúng có thể được sử dụng lại trong nhiều tình huống để ghi lại các mối quan hệ nguyên nhân và hiệu ứng.

  1. Trong MatchManager, tạo một chức năng địa phương mới có tên là stopTimer() . Bên trong, nhập myTimer:stop() để ngừng bộ đếm thời gian.


    -- Tạo một đối tượng hẹn giờ mới để được sử dụng để theo dõi thời gian trận đấu.
    local myTimer = timer.new()
    -- Chức năng địa phương
    local function stopTimer()
    myTimer:stop()
    end
    local function timeUp()
    matchEnd:Fire(gameSettings.endStates.TimerUp)
    end
  2. Để ngăn chặn bộ đếm thời gian khi trận đấu kết thúc, kết nối sự kiện matchEnd với stopTimer() .


    -- Chức năng mô-đun
    function MatchManager.prepareGame()
    playerManager.sendPlayersToMatch()
    matchStart:Fire()
    end
    matchStart.Event:Connect(startTimer)
    matchEnd.Event:Connect(stopTimer)
    return MatchManager
  3. Kiểm tra rằng lỗi trước đó không còn xuất hiện bằng cách khởi động một máy chủ .Loại bỏ tất cả nhưng một người chơi và sau đó chờ vài giây một khi trận đấu kết thúc.

Các bước tiếp theo

Trong khi hai điều kiện chiến thắng đã kết thúc, vẫn còn một số nhiệm vụ còn lại để hoàn thành vòng lặp trò chơi.Ví ví dụ / trường hợp, người chơi chiến thắng không bao giờ được dịch chuyển đến sảnh.Trong bài học tiếp theo, bạn sẽ hiển thị cách trận đấu kết thúc với người chơi và thiết lập lại trò chơi, cuối cùng hoàn thành toàn bộ vòng lặp.

Hoàn thành các kịch bản

Dưới đây là các kịch bản hoàn thành để kiểm tra lại công việc của bạn.

Tập lệnh PlayerManager


local PlayerManager = {}
-- Dịch vụ
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Mô-đun
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
-- Sự kiện
local events = ServerStorage:WaitForChild("Events")
local matchEnd = events:WaitForChild("MatchEnd")
-- Biến bản đồ
local lobbySpawn = workspace.Lobby.StartSpawn
local arenaMap = workspace.Arena
local spawnLocations = arenaMap.SpawnLocations
-- Giá trị
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local playersLeft = displayValues:WaitForChild("PlayersLeft")
-- Biến người chơi
local activePlayers = {}
local playerWeapon = ServerStorage.Weapon
-- Chức năng địa phương
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
-- Chức năng mô-đun
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
-- Sự kiện
Players.PlayerAdded:Connect(onPlayerJoin)
return PlayerManager

Tập lệnh GameSettings


local GameSettings = {}
-- Biến trò chơi
GameSettings.intermissionDuration = 5
GameSettings.matchDuration = 10
GameSettings.minimumPlayers = 2
GameSettings.transitionTime = 5
-- Các cách có thể kết thúc trò chơi.
GameSettings.endStates = {
TimerUp = "TimerUp",
FoundWinner = "FoundWinner"
}
return GameSettings

Tập lệnh GameManager


-- Dịch vụ
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
-- Tập lệnh mô-đun
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local matchManager = require(moduleScripts:WaitForChild("MatchManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
local displayManager = require(moduleScripts:WaitForChild("DisplayManager"))
-- Sự kiện
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()
print("Game ended with: " .. endState)
end

Tập lệnh MatchManager


local MatchManager = {}
-- Dịch vụ
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Tập lệnh mô-đun
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local playerManager = require(moduleScripts:WaitForChild("PlayerManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
local timer = require(moduleScripts:WaitForChild("Timer"))
-- Sự kiện
local events = ServerStorage:WaitForChild("Events")
local matchStart = events:WaitForChild("MatchStart")
local matchEnd = events:WaitForChild("MatchEnd")
-- Giá trị
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local timeLeft = displayValues:WaitForChild("TimeLeft")
-- Tạo một đối tượng hẹn giờ mới để được sử dụng để theo dõi thời gian trận đấu.
local myTimer = timer.new()
-- Chức năng địa phương
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
-- Thêm +1 đảm bảo hiển thị thời gian kết thúc tại 1 thay vì 0.
timeLeft.Value = (myTimer:getTimeLeft() + 1) // 1
-- Bằng cách không đặt thời gian chờ đợi, nó cung cấp lặp lại chính xác hơn
task.wait()
end
end
-- Chức năng mô-đun
function MatchManager.prepareGame()
playerManager.sendPlayersToMatch()
matchStart:Fire()
end
matchStart.Event:Connect(startTimer)
matchEnd.Event:Connect(stopTimer)
return MatchManager