Le partite possono finire in poche condizioni, tra cui il termine dei timer o il lasciare un solo giocatore.
Gestisci i giocatori sconfitti
Al momento, i giocatori sconfitti respawn nell'arena. Invece, inviali alla lobby per aspettare la prossima Corrisponde.
- In PlayerManager, crea una funzione locale chiamata respawnPlayerInLobby() . In quella funzione, fai quanto Seguendo:
- Imposta la proprietà RespawnLocation del Giocatorea lobbySpawn.
- Ricarica il personaggio con Player:LoadCharacter() . Ricorda, LoadCharacter() ricrea il giocatore al loro Rigenerare, rimuovendo tutti gli strumenti che aveva.
Usa funzioni anonime
Le funzioni anonime sono comunemente utilizzate in script avanzati in situazioni specifiche.Prima di definirli, è importante comprendere una situazione che il tuo script può incontrare.
Considera questo: per teletrasportare i giocatori sconfitti nella lobby, la funzione di respawn dovrà essere collegata all'evento Morto del Giocatore.C'è un problema però.Se connetti l'evento come abbiamo fatto in passato, non c'è modo di ottenere il nome del giocatore dall'evento Morto.Lo script ha bisogno di quel nome per rimuovere un giocatore sconfitto dalla tabella che traccia i 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() piuttosto che separatamente.
Una funzione anonima di esempio è quella qui sotto che mostra la sintassi.
myPlayer.Died:Connect(function()
print(player)
end)
Codifica l'evento morto
Per questa funzione, ogni volta che il personaggio di un Giocatoremuore, attiva la funzione che lo fa riapparire.
Per ottenere l'accesso all'evento Died del Giocatore, in PlayerManager > preparePlayer() , aggiungi una variabile per l'umanoide del Giocatore.
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")endCrea una funzione anonima che si connette all'evento Died.Inizia digitando humanoid.Died:Connect() .Quindi, all'interno di Connect() , digita function() , premi Enter per completare automaticamente end e elimina la parentesi extra.
local humanoid = character:WaitForChild("Humanoid")humanoid.Died:Connect(function()end)Nella funzione anonima, chiama respawnPlayerInLobby() . Passa in player , una variabile che memorizza il giocatore che si prepara ad entrare in una Corrisponde.
local humanoid = character:WaitForChild("Humanoid")humanoid.Died:Connect(function()respawnPlayerInLobby(player)end)Avvia un server e gioca una Corrisponde.Prova che quando un giocatore muore, resuscita nella lobby.Per sconfiggere i giocatori, cammina verso di loro e usa l'arma fino a quando non puoi confermare che sono resuscitati nella lobby.
Attaccando Player2 Player2 in Lobby dopo la rigenerazione
Nota, ci sono anche alcuni modi diversi di testare se desiderato.
- Per uccidere un Giocatore, nella finestra Server > Output > Barra dei comandi, copia e pasta: workspace.Player1.Humanoid.Health = 0 .Premi Enter per eseguire il comando.Per rimuovere altri giocatori, usa Player2, Player3, ecc.
- Impostare GameSettings > matchDuration a un tempo più lungo può darti più tempo per trovare e eliminare tutti i giocatori.
- Per avere test più rapidi, cambia GameSettings > minimumPlayers a numero più piccolo, come 2.
Termina il Gioco
Ora che i giocatori sconfitti sono resuscitati, inizia a lavorare per terminare il Gioco.Ricordi di aver creato l'evento MatchEnd? Verrà attivato quando il timer scade o viene trovato un vincitore.
Per dire agli altri script quale condizione ha terminato il Gioco, crea una tabella con le variabili per TimerUp e FoundWinner .Quando termina l'evento della partita, passerà in una variabile in modo che altri script possano rispondere.
In GameSettings, crea una tabella modulo vuota chiamata endStates .
local GameSettings = {}-- Variabili di giocoGameSettings.intermissionDuration = 5GameSettings.matchDuration = 10GameSettings.minimumPlayers = 2GameSettings.transitionTime = 5-- Possibili modi in cui il gioco può Terminare.GameSettings.endStates = {}return GameSettingsCrea due variabili con il nome TimerUp e FoundWinner. Imposta ciascuna a una stringa che corrisponde al loro nome. Queste stringhe verranno utilizzate per testare il codice.
GameSettings.endStates = {TimerUp = "TimerUp",FoundWinner = "FoundWinner"}
Finisci con un timer
Quando il timer termina, lancia l'evento Fine Partita e invia la variabile di stato finale corrispondente.In questo modo, altri script in ascolto di quell'evento possono rispondere di conseguenza.Ricorda che mentre gli eventi inviano segnali di fuoco, possono anche inviare dati che vengono ricevuti da script di ascolto, come TimerUp o FoundWinner .
In GameManager , nel while true do loop, trova la linea matchEnd.Event:Wait() . All'inizio della linea, aggiungi 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()endPer confermare che lo stato corretto è stato ricevuto, aggiungi una dichiarazione di stampa che include 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)endIn MatchManager, trova timeUp() e rimuovi la dichiarazione di stampa.Quindi, per attivare l'evento di fine partita, digita matchEnd:Fire() e passa in gameSettings.endStates.TimerUp.
-- Valorilocal displayValues = ReplicatedStorage:WaitForChild("DisplayValues")local timeLeft = displayValues:WaitForChild("TimeLeft")-- Crea un nuovo oggetto timer da utilizzare per tenere traccia del tempo di partita.local myTimer = timer.new()-- Funzioni localilocal function timeUp()matchEnd:Fire(gameSettings.endStates.TimerUp)endProva una Corrisponde. Una volta che il timer scade, controlla che la dichiarazione di stampa includa la stringa memorizzata nella variabile TimerUp.
Suggerimenti per la risoluzione dei problemi
A questo punto, il messaggio non è stato visualizzato, prova uno dei seguenti.
- Assicurati che ovunque vengano chiamate le variabili di stato finale, che siano scritte esattamente, come qui: gameSettings.endStates.TimerUp .
- Assicurati di utilizzare : (operatore colon) con il Fire() invece del punto operatore, come in matchEnd:Fire() .
Codifica una Corrispondevincente
Successivamente, lo script deve identificare i giocatori vincitori, rimuovere i giocatori perdenti e eseguire la pulizia come l'interruzione del timer.Le partite finiranno anche se un giocatore viene lasciato.Per vedere se la condizione FoundWinner è soddisfatta, avrai bisogno di una funzione che controlli il numero lasciato nella tabella che traccia i giocatori in una Corrisponde.
Controlla il numero di giocatori
Le partite finiranno se rimane un solo giocatore.Per controllare questo, lo script deve tracciare i giocatori in una partita.Una volta che un giocatore è stato lasciato, può essere assegnato un vincitore.
In PlayerManager, definisci le seguenti variabili:
- Cartella ModuleScripts
- Modulo GameSettings - Utilizzato per accedere alle variabili di stato finale
- Cartella eventi e evento MatchEnd - Evento Fires
local PlayerManager = {}-- Servizilocal Players = game:GetService("Players")local ServerStorage = game:GetService("ServerStorage")local ReplicatedStorage = game:GetService("ReplicatedStorage")-- Modulilocal moduleScripts = ServerStorage:WaitForChild("ModuleScripts")local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))-- Eventilocal events = ServerStorage:WaitForChild("Events")local matchEnd = events:WaitForChild("MatchEnd")Sopra respawnPlayerInLobby(), aggiungi una nuova funzione locale chiamata checkPlayerCount().
-- Variable del giocatorelocal activePlayers = {}local playerWeapon = ServerStorage.Weaponlocal function checkPlayerCount()endlocal function respawnPlayerInLobby(player)All'interno di quella funzione, usa una dichiarazione if poi per controllare un vincitore. In quella dichiarazione:
- Verifica se la dimensione della tabella activePlayers è 1.
- Se è così, spara matchEnd e passa in gameSettings.endStates.FoundWinner .
local function checkPlayerCount()if #activePlayers == 1 thenmatchEnd:Fire(gameSettings.endStates.FoundWinner)endend
Rimuovi un Giocatore
Un conteggio accurato non può essere mantenuto a meno che i giocatori non vengono rimossi.Quando un giocatore viene sconfitto, mantieni un conteggio accurato dei giocatori rimuovendoli dalla tabella del giocatore.Quindi, controlla le dimensioni della tabella dei giocatori attivi per vedere se c'è un vincitore.
Sotto checkPlayerCount(), crea una nuova funzione locale con il nome removeActivePlayer() con un parametro chiamato player .
local function checkPlayerCount()if #activePlayers == 1 thenmatchEnd:Fire(gameSettings.endStates.FoundWinner)endendlocal function removeActivePlayer(player)endPer trovare il giocatore nella tabella activePlayers, iterare attraverso di essa utilizzando un ciclo for.Quindi, aggiungi una dichiarazione if che viene eseguita se un giocatore che corrisponde al nome viene trovato nella funzione.
local function removeActivePlayer(player)for playerKey, whichPlayer in activePlayers doif whichPlayer == player thenendendendPer rimuovere il Giocatore, nella dichiarazione if:
- Chiama table.remove() . Dentro i parentesi, passa in activePlayers , la tabella da guardare e playerKey - il giocatore da rimuovere dalla tabella.
- Imposta il valore dell'oggetto playersLeft a #activePlayers.
- Controlla un giocatore vincitore eseguendo checkPlayerCount() .
local function removeActivePlayer(player)for playerKey, whichPlayer in activePlayers doif whichPlayer == player thentable.remove(activePlayers, playerKey)playersLeft.Value = #activePlayerscheckPlayerCount()endendend
Connetti eventi e test
Per utilizzare la funzione appena creata, chiamala dall'interno della funzione anonima connessa all'evento Died del Giocatore.
Trova preparePlayer() . Nella funzione anonima con la connessione evento Died, chiama removeActivePlayer() . Quindi, passa nel giocatore come parametro.
humanoid.Died:Connect(function()respawnPlayerInLobby(player)removeActivePlayer(player)end)Per vedere se viene trovato un giocatore vincitore, avvia un test server .Quando manca solo un giocatore dovresti vedere FoundWinner nella finestra di output.
Continua a testare e lascia che la partita Terminare. Nota come una nuova partita inizia, un errore appare nella finestra di output:
Questo errore è dovuto al fatto che il timer non è stato interrotto, che verrà corretto nella sezione successiva.
Fermare il timer
Ogni volta che una partita termina con un Giocatorevincitore, il timer deve fermarsi anche.Per interrompere il timer prima che scada il tempo, fai in modo che il timer si fermi ogni volta che si attiva l'evento di fine partita.Questo è uno dei vantaggi della creazione di eventi.Possono essere riutilizzati in molte situazioni per scriptare le relazioni causa-effetto.
In MatchManager, crea una nuova funzione locale chiamata stopTimer() . All'interno, digita myTimer:stop() per fermare il timer.
-- Crea un nuovo oggetto timer da utilizzare per tenere traccia del tempo di partita.local myTimer = timer.new()-- Funzioni localilocal function stopTimer()myTimer:stop()endlocal function timeUp()matchEnd:Fire(gameSettings.endStates.TimerUp)endPer interrompere il timer quando la partita finisce, collega l'evento matchEnd a stopTimer() .
-- Funzioni del modulofunction MatchManager.prepareGame()playerManager.sendPlayersToMatch()matchStart:Fire()endmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManagerTest che l'errore precedente non appare più avviando un server .Elimina tutti ma un giocatore e poi aspetta qualche secondo una volta che la partita finisce.
Prossimi passi
Mentre le due condizioni di vittoria sono finite, ci sono ancora alcuni compiti da completare il ciclo di gioco.Ad esempio, il giocatore vincitore non viene mai teletrasportato nella lobby.Nella lezione successiva, mostrerai come la partita sia finita ai giocatori e ripristinerai il Gioco, completando infine l'intero ciclo.
Script completati
Di seguito sono completati gli script per controllare due volte il tuo lavoro.
scriptdi PlayerManager
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")
-- Variable 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
scriptdelle impostazioni di gioco
local GameSettings = {}-- Variabili di giocoGameSettings.intermissionDuration = 5GameSettings.matchDuration = 10GameSettings.minimumPlayers = 2GameSettings.transitionTime = 5-- Possibili modi in cui il gioco può Terminare.GameSettings.endStates = {TimerUp = "TimerUp",FoundWinner = "FoundWinner"}return GameSettings
scriptdi GameManager
-- Servizilocal ServerStorage = game:GetService("ServerStorage")local Players = game:GetService("Players")-- Script del modulolocal moduleScripts = ServerStorage:WaitForChild("ModuleScripts")local matchManager = require(moduleScripts:WaitForChild("MatchManager"))local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))local displayManager = require(moduleScripts:WaitForChild("DisplayManager"))-- Eventilocal 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
scriptdi 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 da utilizzare per tenere traccia del tempo di 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
-- Aggiungere +1 assicura che la visualizzazione del timer finisca a 1 invece di 0.
timeLeft.Value = (myTimer:getTimeLeft() + 1) // 1
-- Non impostando l'ora 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