Partite Finali

*Questo contenuto è tradotto usando AI (Beta) e potrebbe contenere errori. Per visualizzare questa pagina in inglese, clicca qui.

Le partite possono finire in una o più condizioni tra cui i timer esauriscono o un singolo giocatore viene lasciato.

Gestire i giocatori sconfitti

Al momento, i giocatori sconfitti respawnano nell'arena. Invece, inviali al lobby per attendere il prossimo Corrisponde.

  1. In PlayerManager, crea una funzione locale chiamata respawnPlayerInLobby() . In quella funzione, fai le Seguendooperazioni:
  • Imposta la proprietà RespawnLocation del Giocatorenella lobbySpawn.
  • Ricarica il personaggio con Player:LoadCharacter() . Ricorda, LoadCharacter() ricrea il giocatore al loro Rigenerare, rimuovendo tutti gli strumenti che aveva.

Uso di funzioni anonime

Le funzioni anonime sono comunemente utilizzate in script avanzati in situazioni specifiche. Prima di definirle, è importante capire una situazione che il tuo script potrebbe incontrare.

Considera questo: per teletrasportare i giocatori sconfitti nella lobby, la funzione respawn dovrà essere connessa all'evento Died del Giocatore. C'è un problema, però. Se connetti l'evento come abbiamo fatto in passato, non ci sono modi per ottenere il nome del giocatore dall'evento Died. Lo script ha bisogno di questo nome per rimuovere un giocatore sconfitto dalla tabella di tracciamento dei giocatori attivi.

Per ottenere il nome del giocatore che ha attivato l'evento Died, usa una funzione anonima. Le funzioni anonime non hanno nomi, e possono essere create direttamente all'interno di Connect() invece di separatamente.

Un esempio di funzione anonima è sotto che mostra la sintassi.


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

Codice dell'evento morto

Per questa funzione, ogni volta che il personaggio di un Giocatoremuore, attiva la funzione che li respinge.

  1. Per ottenere l'accesso all'evento Died del Giocatore, in PlayerManager > preparePlayer() , aggiungi una variabile per l'uomoide del Giocatore.


    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. Crea un'anonima funzione che si connette all'evento Died. Start by typing humanoid.Died:Connect() . Quindi, dentro Connect() , scrivi 1> function()1> , premi 4> Enter 4> to autocompletare 7> Terminare7> , e elimina la parentesi extra.


    local humanoid = character:WaitForChild("Humanoid")
    humanoid.Died:Connect(function()
    end)
  3. Nella funzione anonima, chiama respawnPlayerInLobby() . Passa in player, una variabile che memorizza il giocatore che si prepara a entrare in una Corrisponde.


    local humanoid = character:WaitForChild("Humanoid")
    humanoid.Died:Connect(function()
    respawnPlayerInLobby(player)
    end)
  4. Avvia un server e gioca una Corrisponde. Prova che quando un giocatore muore, respawna nella lobby. Per sconfiggere i giocatori, avvicinati a loro e usa la tua arma fino a quando non puoi confermare che sono respawnati nella lobby.

    Attaccando Player2
    Player2 nella Lobby dopo la rigenerazione

Nota, ci sono anche alcuni modi diversi di testare se lo desideri.

  • Per uccidere un Giocatore, nella Server >Output Window > Command Bar, copia e pasta: workspace.Player1.Humanoid.Health = 0 . Premi Inserisci per eseguire il comando. Per rimuovere altri giocatori, usa Player2, Player3, etc.
  • Impostare GameSettings > matchDuration in un tempo più lungo può darti più tempo per trovare e eliminare tutti i giocatori.
  • Per avere test più veloci, cambia GameSettings > minimumPlayers in un numero più piccolo, come 2.

Finire il gioco

Ora che i giocatori sconfitti respawn, inizia a lavorare per terminare il Gioco. Ricorda di creare l'evento MatchEnd? Verrà attivato quando il timer finisce o un vincitore viene trovato.

Per dire agli altri script che condizione ha terminato il Gioco, crea una tabella con variabili per TimerUp e FoundWinner . Quando si attiva l'evento di fine partita, passa in una variabile in modo che altri script possano rispondere.

  1. In GameSettings, create un'istanza modulo vuota chiamata endStates .


    local GameSettings = {}
    -- Variabili di gioco
    GameSettings.intermissionDuration = 5
    GameSettings.matchDuration = 10
    GameSettings.minimumPlayers = 2
    GameSettings.transitionTime = 5
    -- Possibili modi in cui il gioco può Terminare.
    GameSettings.endStates = {
    }
    return GameSettings
  2. Crea due variabili chiamati TimerUp e FoundWinner . Imposta ciascuna di queste variabili su una stringa corrispondente al loro nome. Queste stringhe saranno utilizzate per testare il codice.


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

Finire con un timer

Quando il timer finisce, fire the Match End event and send the matching end state variable. That way, other scripts listening for that event can respond accordingly. Ricorda che mentre gli eventi fire i segnali, that can also send data that's received by listening script, like TimerUp or FoundWinner .

  1. In GameManager , in while true do loop, find the line matchEnd.Event:Wait() . At the start of the line, add 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. Per confermare che lo stato corretto è stato ricevuto, aggiungi una dichiarazione di stampa includendo 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. In MatchManager, find timeUp() and rimuovi la dichiarazione di stampa. Then, to fire the match end event, type matchEnd:Fire() and pass in 1> gameSettings.endSettings.TimerUp1> .


    -- Valori
    local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
    local timeLeft = displayValues:WaitForChild("TimeLeft")
    -- Crea un nuovo oggetto timer per essere utilizzato per tracciare il tempo della partita.
    local myTimer = timer.new()
    -- Funzioni locali
    local function timeUp()
    matchEnd:Fire(gameSettings.endStates.TimerUp)
    end
  4. Prova un Corrisponde. Una volta che il timer si esaurisce, controlla che la dichiarazione di stampa includa la stringa memorizzata nella variabile TimerUp .

Risolvere i problemi

Al momento, il messaggio non è stato visualizzato, prova uno dei seguenti sotto.

  • Assicurati che ovunque le variabili di stato di fine siano chiamate, che siano scritte esattamente, come qui: gameSettings.endStates.TimerUp .
  • Assicurati di utilizzare : (operatore colon) con il Fire() вместо dell'operatore punto, come in matchEnd:Fire() .

Codere una partita vincente

Successivamente, lo script deve identificare i giocatori vincitori, rimuovere i giocatori perdenti e eseguire pulizie come l'interruzione del timer. Le partite finiranno anche se un giocatore viene lasciato. Per vedere se la condizione FoundWinner è soddisfatta, è necessaria una funzione che controlla il numero rimasto nella tabella tracciando i giocatori in una Corrisponde.

Conteggio dei giocatori

Le partite finiranno se rimane solo un giocatore. Per controllare questo, lo script deve tracciare i giocatori in un round. Una volta che un giocatore è uscito, un vincitore può essere assegnato.

  1. In PlayerManager, definisci le seguenti variabili:

    • Cartella ModulScripts
    • GameSettings module - Used to access end state variables
    • Eventi cartella e l'evento MatchEnd - Fires event

    local PlayerManager = {}
    -- Servizi
    local Players = game:GetService("Players")
    local ServerStorage = game:GetService("ServerStorage")
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    -- Moduli
    local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
    local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
    -- Eventi
    local events = ServerStorage:WaitForChild("Events")
    local matchEnd = events:WaitForChild("MatchEnd")
  2. Oltre respawnPlayerInLobby() , aggiungi una nuova funzione locale chiamata checkPlayerCount() .


    -- Variabili del giocatore
    local activePlayers = {}
    local playerWeapon = ServerStorage.Weapon
    local function checkPlayerCount()
    end
    local function respawnPlayerInLobby(player)
  3. All'interno di quella funzione, usa un if then statement per controllare per un vincitore. In quella dichiarazione:

    • Controlla se la dimensione della tabella activePlayers è 1.
    • Se è così, fire matchEnd e pass in gameSettings.endStates.FoundWinner .

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

Rimuovere un giocatore

Un conteggio preciso non può essere mantenuto a meno che i giocatori non siano rimossi. Quando un giocatore viene sconfitto, mantieni un conteggio preciso dei giocatori rimuovendoli dalla tabella dei giocatori. Quindi, controlla la dimensione della tabella dei giocatori attivi per vedere se c'è un vincitore.

  1. Sotto checkPlayerCount() , crea una nuova funzione locale chiamata removeActivePlayer() con un parametro chiamato player .


    local function checkPlayerCount()
    if #activePlayers == 1 then
    matchEnd:Fire(gameSettings.endStates.FoundWinner)
    end
    end
    local function removeActivePlayer(player)
    end
  2. Per trovare il giocatore nella tabella activePlayers, ripeti attraverso di essa utilizzando un loop for . Quindi, aggiungi una dichiarazione if che viene eseguita se un giocatore corrispondente al nome viene trovato nella funzione.


    local function removeActivePlayer(player)
    for playerKey, whichPlayer in activePlayers do
    if whichPlayer == player then
    end
    end
    end
  3. Per rimuovere il Giocatore, nell'if statement:

    • Chiama table.remove() . All'interno dei parentesi, passa in activePlayers , la tabella da cui guardare e playerKey - il giocatore da rimuovere dalla tabella.
    • Imposta il valore dell'oggetto playersLeft su #activePlayers .
    • Controlla un giocatore vincitore eseguendo 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

Connessione degli eventi e test

Per utilizzare la funzione appena creata, chiamala dall'interno dell'evento anonimo connesso all'evento Died del Giocatore.

  1. Trova preparePlayer() . In the anonymous function with the Died event connection, call removeActivePlayer() . Then, pass in the player as the parameter.


    humanoid.Died:Connect(function()
    respawnPlayerInLobby(player)
    removeActivePlayer(player)
    end)
  2. Per vedere se un giocatore vincitore è stato trovato, avvia un test server . Quando c'è solo un giocatore rimasto, dovresti vedere FoundWinner nella finestra di uscita.

  3. Continua a testare e lascia che la partita Terminare. Nota come una nuova partita inizia, un errore appare nella finestra di uscita:

Questo errore è dovuto al fatto che il timer non è stato fermato, che sarà risolto nella prossima sezione.

Interruzione del timer

Quando una partita finisce con un Giocatorevincitore, il timer dovrebbe fermarsi anche. Per fermare il timer prima che il tempo scada, fai in modo che il timer si fermi ogni volta che si attiva l'evento di fine partita. Questo è uno dei benefici della creazione di eventi. Possono essere riutilizzati in più situazioni per script causare e effetto relazioni.

  1. In MatchManager, crea una nuova funzione locale chiamata stopTimer() . All'interno, digita myTimer:stop() per fermare il timer.


    -- Crea un nuovo oggetto timer per essere utilizzato per tracciare il tempo della partita.
    local myTimer = timer.new()
    -- Funzioni locali
    local function stopTimer()
    myTimer:stop()
    end
    local function timeUp()
    matchEnd:Fire(gameSettings.endStates.TimerUp)
    end
  2. Per interrompere il timer quando la partita finisce, connect the matchEnd event to stopTimer() .


    -- Funzioni del modulo
    function MatchManager.prepareGame()
    playerManager.sendPlayersToMatch()
    matchStart:Fire()
    end
    matchStart.Event:Connect(startTimer)
    matchEnd.Event:Connect(stopTimer)
    return MatchManager
  3. Prova che l'errore precedente non appare più avviando un server . Elimina tutti ma un giocatore e poi aspetta pochi secondi una volta terminata la partita.

Prossimi passi

Mentre le due condizioni di vittoria sono finiti, ci sono ancora alcuni compiti rimasti per completare il ciclo di gioco. Ad esempio, il giocatore vincitore non viene mai teletrasportato nella lobby. Nel prossimo lezione, mostrerai come la partita è finita per i giocatori e ripristinerai il Gioco, quindi completando così l'intero ciclo.

Script completati

Di seguito sono gli script completati per il doppio controllo del tuo lavoro.

Script del lettore


local PlayerManager = {}
-- Servizi
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Moduli
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
-- Eventi
local events = ServerStorage:WaitForChild("Events")
local matchEnd = events:WaitForChild("MatchEnd")
-- Variabili di mappa
local lobbySpawn = workspace.Lobby.StartSpawn
local arenaMap = workspace.Arena
local spawnLocations = arenaMap.SpawnLocations
-- Valori
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local playersLeft = displayValues:WaitForChild("PlayersLeft")
-- Variabili del giocatore
local activePlayers = {}
local playerWeapon = ServerStorage.Weapon
-- Funzioni locali
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
-- Funzioni del modulo
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
-- Eventi
Players.PlayerAdded:Connect(onPlayerJoin)
return PlayerManager

Script di GameSettings


local GameSettings = {}
-- Variabili di gioco
GameSettings.intermissionDuration = 5
GameSettings.matchDuration = 10
GameSettings.minimumPlayers = 2
GameSettings.transitionTime = 5
-- Possibili modi in cui il gioco può Terminare.
GameSettings.endStates = {
TimerUp = "TimerUp",
FoundWinner = "FoundWinner"
}
return GameSettings

Script del GameManager


-- Servizi
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
-- Script del modulo
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local matchManager = require(moduleScripts:WaitForChild("MatchManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
local displayManager = require(moduleScripts:WaitForChild("DisplayManager"))
-- Eventi
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

Script del MatchManager


local MatchManager = {}
-- Servizi
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Script del modulo
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local playerManager = require(moduleScripts:WaitForChild("PlayerManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
local timer = require(moduleScripts:WaitForChild("Timer"))
-- Eventi
local events = ServerStorage:WaitForChild("Events")
local matchStart = events:WaitForChild("MatchStart")
local matchEnd = events:WaitForChild("MatchEnd")
-- Valori
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local timeLeft = displayValues:WaitForChild("TimeLeft")
-- Crea un nuovo oggetto timer per essere utilizzato per tracciare il tempo della partita.
local myTimer = timer.new()
-- Funzioni locali
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
-- L'aggiunta di +1 assicura che il timer finisca a 1 invece di 0.
timeLeft.Value = (math.floor(myTimer:getTimeLeft() + 1))
-- Impostando il tempo di attesa, offre un looping più preciso
task.wait()
end
end
-- Funzioni del modulo
function MatchManager.prepareGame()
playerManager.sendPlayersToMatch()
matchStart:Fire()
end
matchStart.Event:Connect(startTimer)
matchEnd.Event:Connect(stopTimer)
return MatchManager