Kończące się mecze

*Ta zawartość została przetłumaczona przy użyciu narzędzi AI (w wersji beta) i może zawierać błędy. Aby wyświetlić tę stronę w języku angielskim, kliknij tutaj.

Rozgrywki mogą zakończyć się na kilku warunkach, w tym skończą się zegarki lub pojedynczy gracz zostanie opuszczony.

Zarządzanie pokonanymi graczami

Obecnie pokonani gracze respawnują na arenie. Zamiast tego wysyłaj ich z powrotem do lobby, aby czekać na następny dopasowywać.

  1. W PlayerManagerze utwórz lokalną funkcję nazyającą się respawnPlayerInLobby() . W tej funkcji zrób obserwuje:
  • Ustaw właściwość RespawnLocation gracza na lobbySpawn.
  • Przeładuj postać za pomocą Player:LoadCharacter(). Pamiętaj, że LoadCharacter() odtwarza gracza na ich spawn, usuwając wszystkie narzędzia, które mieli.

Używanie anonimowych funkcji

Anonimowe funkcje są powszechnie używane w zaawansowanych skryptach pod specjalnymi sytuacjami. Zanim je zdefiniujesz, ważne jest, aby zrozumieć sytuację, która może się pojawić w Twoim skrypcie.

Rozważ to: Aby przenieść pokonanych graczy do lobby, funkcja respawn będzie musiała być połączona z wydarzeniem Died gracza. Jest jednak problem. Jeśli połączysz funkcję respawn z wydarzeniem Died, nie będzie można uzyskać imienia gracza z wydarzenia Died. Skrypt potrzebuje tego imienia, aby usunąć pokonanego gracza z tablicy śledzenia aktywnych graczy.

Aby uzyskać nazwę gracza, który wywołał wydarzenie umarłego, użyj anonimowej funkcji. Anonimowe funkcje nie mają imion i można je tworzyć bezpośrednio w Connect() zamiast oddzielnie.

Poniżej znajduje się próbna, anonimowa funkcja, która pokazuje sintaksę.


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

Kodowanie martwego wątku

Dla tej funkcji, gdy każdy postać gracza umiera, zawsze wyzwala funkcję, która je respawnuje.

  1. Aby uzyskać dostęp do wydarzenia Zmarłego gracza w PlayerManager > preparePlayer(), dodaj zmienne dla ludoidu gracza.


    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. Utwórz anonimową funkcję, która łączy się z wydarzeniem Zmarł. Rozpocznij, pisząc humanoid.Died:Connect() . Następnie, w środku dentro Connect() , wpisz 1> function()1> , naciśnij 4> Enter4> do ukończenia 7> kończyć7> i us


    local humanoid = character:WaitForChild("Humanoid")
    humanoid.Died:Connect(function()
    end)
  3. W funkcji anonimowej, wezwij respawnPlayerInLobby() . Przekaż w player , zmienne przechowywane przez gracza, aby wejść do dopasowywać.


    local humanoid = character:WaitForChild("Humanoid")
    humanoid.Died:Connect(function()
    respawnPlayerInLobby(player)
    end)
  4. Rozpocznij serwer i zagraj w dopasowywać. Testuj, że gdy gracz umiera, respawnuje w lobby. Aby pokonać graczy, podejdź do nich i użyj swojej broni, aż będziesz pewien, że ​​zrespawnowali w lobby.

    Atakuj gracza 2
    Gracz2 w Lobby po odrodzeniu

Uwaga, istnieją również pewne różne sposoby testowania, jeśli chcesz.

  • Aby zabić gracza, w oknie Server > Wyjście > Barwnik, skopiuj i wklej: workspace.Player1.Humanoid.Health = 0 . Naciśnij Enter, aby uruchomić komendę. Aby usunąć innych graczy, użyj Player2, Player3 itp.
  • Ustawienie GameSettings > matchDuration może dać ci więcej czasu na znalezienie i usunięcie wszystkich graczy.
  • Aby mieć szybsze testy, zmień GameSettings > minimumPlayers do mniejszej liczby, jak 2.

Zakończenie gry

Teraz, gdy pokonani gracze respawn, zacznij pracować nad zakończeniem gry. Pamiętaj o tworzeniu wydarzenia końca meczu? Zostanie ono uruchomione, gdy skończy się odliczanie lub znajdzie się zwycięzca.

Aby powiedzieć innym skryptom, które zakończyły gra, stwórz tabelę z zmienne dla TimerUp i FoundWinner. Gdy wydarzenie końca pojedynczego meczu zostanie uruchomione, będzie przekazywane zmienne, aby inne skrypty mogły na niego odpowiedzieć.

  1. W GameSettings utwórz pustą tabelę modułów nazyającą się endStates .


    local GameSettings = {}
    -- Zróżnicowane gry
    GameSettings.intermissionDuration = 5
    GameSettings.matchDuration = 10
    GameSettings.minimumPlayers = 2
    GameSettings.transitionTime = 5
    -- Możliwe sposoby, w jaki może zakończyć się gra.
    GameSettings.endStates = {
    }
    return GameSettings
  2. Utwórz dwa zmienne nazyające się TimerUp i FoundWinner. Ustaw każde z nich na strunę pasującą z ich imienia. Te struny będą używane do testowania kodu.


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

Kończenie z Timer

Gdy skończy się odliczanie, zakończ wydarzenie „Koniec meczu” i wysyłaj zmienną stanu końcowego dopasu. W ten sposób inne skrypty słuchające tego wydarzenia mogą odpowiedzieć odpowiednio. Pamiętaj, że podczas gdy wydarzenia słuchają sygnałów czasu, można również wysyłać dane otrzymane przez słuchające skrypty, takie jak TimerUp lub FoundWinner

  1. W GAMEManager , w czasie prawdziwy do pętli, znajdź linii matchEnd.Event:Wait(). Na początku linii, dodaj 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. Aby potwierdzić, że otrzymano poprawny stan, dodaj oświadczenie drukowania zawierające 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. W MatchManager, znajdź timeUp() i usuń drukową stwierdzenie. Następnie, aby uruchomić wydarzenie końcowe meczu, wpisz matchEnd:Fire() i wpisz 2> gameSettings.endSettings.timerUp2>.


    -- Wartości
    local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
    local timeLeft = displayValues:WaitForChild("TimeLeft")
    -- Tworzy nowy obiekt timer, aby używać do śledzenia czasu meczu.
    local myTimer = timer.new()
    -- Lokalne funkcje
    local function timeUp()
    matchEnd:Fire(gameSettings.endStates.TimerUp)
    end
  4. Sprawdź dopasowywać. Po wykonaniu się zegarza upewnij się, że drukowanie oświadczenia zawiera zmienną TimerUp.

Wskazówki dotyczące rozwiązywania problemów

W tym momencie wiadomość nie była wyświetlana, spróbuj jednej z poniższych opcji.

  • Sprawdź, gdziekolwiek zakończyły się zmienne stanu końcowego, że są one napisane dokładnie, jak tutaj: gameSettings.endStates.TimerUp .
  • Upewnij się użycia : (operator kolbowy) z operatorem Fire() zamiast operatora kropki, jak w matchEnd:Fire().

Kodowanie wygranego mecze

Następnie skrypt musi zidentyfikować zwycięzców, usunąć przegranych graczy i wykonać czyszczenie takie jak zatrzymanie licznika. Rozgrywki zakończą się również, jeśli jeden gracz zostanie opuszony. Aby zobaczyć, czy kondycja FoundWinner zostanie spełniona, będziesz potrzebować funkcji, która sprawdza liczbę pozostałą w tabeli śledzenia graczy w dopasowywać.

Sprawdzanie liczby graczy

Rozgrywki zakończą się, jeśli pozostanie tylko jeden gracz. Aby to sprawdzić, skrypt musi śledzić graczy w rundzie. Po pozwoleniu jednego gracza można przypisać zwycięzcę.

  1. W PlayerManager określ następujące zmienne:

    • Katalog Modułów
    • Moduł GameSettings - Używany do dostępu do zmiennej stanu końcowego
    • Katalog wydarzeń i wydarzenie MatchEnd - Ognia wydarzenie

    local PlayerManager = {}
    -- Usługi
    local Players = game:GetService("Players")
    local ServerStorage = game:GetService("ServerStorage")
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    -- Moduły
    local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
    local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
    -- Wydarzenia
    local events = ServerStorage:WaitForChild("Events")
    local matchEnd = events:WaitForChild("MatchEnd")
  2. Ponad respawnPlayerInLobby() , dodaj nową lokalną funkcję nazyającą się checkPlayerCount() .


    -- Zróżnicowane zmienne
    local activePlayers = {}
    local playerWeapon = ServerStorage.Weapon
    local function checkPlayerCount()
    end
    local function respawnPlayerInLobby(player)
  3. W ramach tej funkcji użyj if then, aby sprawdzić, czy istnieje zwycięzca. W tej funkcji:

    • Sprawdź, czy rozmiar tabeli activePlayers jest 1.
    • Jeśli tak, to matchEnd firek gameSettings.endStates.FoundWinner i przekaż gameSettings.endSettings.FoundWinner .

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

Usuwanie gracza

Dokładna liczba nie może być utrzymywana, chyba że gracze zostaną usunięci. Gdy gracz jest pokonany, utrzymuj dokładną liczbę graczy, usuwając ich z tabeli graczy. Następnie sprawdź rozmiar aktywnej tabeli gracza, aby ujrzeć, czy istnieje zwycięzca.

  1. Pod checkPlayerCount(), utwórz nową lokalną funkcję nazwaną removeActivePlayer() z parametrem nazwanym player.


    local function checkPlayerCount()
    if #activePlayers == 1 then
    matchEnd:Fire(gameSettings.endStates.FoundWinner)
    end
    end
    local function removeActivePlayer(player)
    end
  2. Aby znaleźć gracza w tabeli activePlayers, przeszukaj go używając for pętli. Następnie dodaj if oświadczenie, które będzie wykonane, jeśli gracz pasujący imieniem znajdzie się w funkcji.


    local function removeActivePlayer(player)
    for playerKey, whichPlayer in activePlayers do
    if whichPlayer == player then
    end
    end
    end
  3. Aby usunąć gracza, w if statement:

    • Zadzwoń do table.remove() . Wewnątrz nawiasów przekaż activePlayers , tabelę do zobaczenia i playerKey - gracza do usunięcia z tabeli.
    • Ustaw wartość obiektu playersLeft na #activePlayers.
    • Sprawdź zwycięzcę poprzez uruchomienie 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

Łączenie wydarzeń i testowanie

Aby użyć funkcji właśnie utworzonej, wezwij ją z anonimowej funkcji połączonej z wydarzeniem Died gracza.

  1. Znajdź preparePlayer() . W anonimowej funkcji z połączeniem wydarzenia Zmarł z wewnętrzną funkcją removeActivePlayer() . Następnie przekaż parametr gracza.


    humanoid.Died:Connect(function()
    respawnPlayerInLobby(player)
    removeActivePlayer(player)
    end)
  2. Aby zobaczyć, czy znaleziono zwycięzcę, uruchom serwer testowy . Gdy jest tylko jeden gracz, powinieneś zobaczyć ZnalezionyWygrać w okienku wyjścia.

  3. Kontynuuj testy i pozwól meczowi się zakończyć. Zauważ, jak nowy mecz się rozpocznie, błąd pojawi się w oknie wyjścia:

Ten błąd jest spowodowany przez to, że licznik nie został zatrzymany, co zostanie naprawione w następnym sezonie.

Zatrzymanie licznika

Kiedykolwiek mecz zakończy się przegrywającym graczem, zatrzymaj zegar również. Aby zatrzymać zegar przed upływem czasu, zatrzymaj zegar, gdy wydarzenie końca mecza się zapali. Jest to jeden z korzyści płynących z tworzenia wydarzeń. Mogą być one ponowane w wielu sytuacjach, aby skrypt powoduje i efekt relacji.

  1. W MatchManager utwórz nową lokalną funkcję nazyającą się stopTimer() . Wewnątrz, wpisz myTimer:stop() , aby zatrzymać zegar.


    -- Tworzy nowy obiekt timer, aby używać do śledzenia czasu meczu.
    local myTimer = timer.new()
    -- Lokalne funkcje
    local function stopTimer()
    myTimer:stop()
    end
    local function timeUp()
    matchEnd:Fire(gameSettings.endStates.TimerUp)
    end
  2. Aby zatrzymać licznik czasu, gdy mecz się kończy, połącz wydarzenie końca mecze z stopTimer() .


    -- Funkcje modułu
    function MatchManager.prepareGame()
    playerManager.sendPlayersToMatch()
    matchStart:Fire()
    end
    matchStart.Event:Connect(startTimer)
    matchEnd.Event:Connect(stopTimer)
    return MatchManager
  3. Testuj , że poprzedni błąd nie pojawia się już poprzez uruchomienie serwera . Eliminuj wszystkie, z wyjątkiem jednego gracza i czekaj kilka sekund po zakończeniu meczu.

Kolejne kroki

Gdy dwa warunki wygrane są zakończone, nadal pozostają niektóre zadania do ukończenia pętli gry. Na instancja, wygrywający gracz nie zostanie nigdy przeniesiony do lobby. W następnym lekcji pokażesz, jak mecz zakończył się dla graczy i zresetujesz grę, aby w końcu ukończyć cały pętli.

Ukończone Skrypcity

Poniżej znajdują się zakończone skrypty, aby podwoić sprawdzenie swojej pracy.

Skrypt PlayerManager


local PlayerManager = {}
-- Usługi
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Moduły
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
-- Wydarzenia
local events = ServerStorage:WaitForChild("Events")
local matchEnd = events:WaitForChild("MatchEnd")
-- Zróżnicowane Mapy
local lobbySpawn = workspace.Lobby.StartSpawn
local arenaMap = workspace.Arena
local spawnLocations = arenaMap.SpawnLocations
-- Wartości
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local playersLeft = displayValues:WaitForChild("PlayersLeft")
-- Zróżnicowane zmienne
local activePlayers = {}
local playerWeapon = ServerStorage.Weapon
-- Lokalne funkcje
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
-- Funkcje modułu
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
-- Wydarzenia
Players.PlayerAdded:Connect(onPlayerJoin)
return PlayerManager

Skrypt GameSettings


local GameSettings = {}
-- Zróżnicowane gry
GameSettings.intermissionDuration = 5
GameSettings.matchDuration = 10
GameSettings.minimumPlayers = 2
GameSettings.transitionTime = 5
-- Możliwe sposoby, w jaki może zakończyć się gra.
GameSettings.endStates = {
TimerUp = "TimerUp",
FoundWinner = "FoundWinner"
}
return GameSettings

Skrypt GameManager


-- Usługi
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
-- Skripty modułu
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local matchManager = require(moduleScripts:WaitForChild("MatchManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
local displayManager = require(moduleScripts:WaitForChild("DisplayManager"))
-- Wydarzenia
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

Skrypt MatchManager


local MatchManager = {}
-- Usługi
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Skripty modułu
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local playerManager = require(moduleScripts:WaitForChild("PlayerManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
local timer = require(moduleScripts:WaitForChild("Timer"))
-- Wydarzenia
local events = ServerStorage:WaitForChild("Events")
local matchStart = events:WaitForChild("MatchStart")
local matchEnd = events:WaitForChild("MatchEnd")
-- Wartości
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local timeLeft = displayValues:WaitForChild("TimeLeft")
-- Tworzy nowy obiekt timer, aby używać do śledzenia czasu meczu.
local myTimer = timer.new()
-- Lokalne funkcje
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
-- Dodanie +1 upewnia się, że ekran zlicznika kończy się na 1, a nie na 0.
timeLeft.Value = (math.floor(myTimer:getTimeLeft() + 1))
-- Nie ustawiając czasu na czekanie, oferuje ono bardziej dokładne pętlenie
task.wait()
end
end
-- Funkcje modułu
function MatchManager.prepareGame()
playerManager.sendPlayersToMatch()
matchStart:Fire()
end
matchStart.Event:Connect(startTimer)
matchEnd.Event:Connect(stopTimer)
return MatchManager