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.
- 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.
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 = whichSpawnplayer:LoadCharacter()local character = player.Character or player.CharacterAdded:Wait()local sword = playerWeapon:Clone()sword.Parent = characterlocal humanoid = character:WaitForChild("Humanoid")endCrea 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)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)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.
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.
In GameSettings, create un'istanza 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 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 .
In GameManager , in while true do loop, find the line matchEnd.Event:Wait() . At the start of the line, add 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 includendo 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, 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> .
-- Valorilocal 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 localilocal function timeUp()matchEnd:Fire(gameSettings.endStates.TimerUp)endProva 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.
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 = {}-- 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")Oltre respawnPlayerInLobby() , aggiungi una nuova funzione locale chiamata checkPlayerCount() .
-- Variabili del giocatorelocal activePlayers = {}local playerWeapon = ServerStorage.Weaponlocal function checkPlayerCount()endlocal function respawnPlayerInLobby(player)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 thenmatchEnd:Fire(gameSettings.endStates.FoundWinner)endend
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.
Sotto checkPlayerCount() , crea una nuova funzione locale chiamata 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, 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 doif whichPlayer == player thenendendendPer 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 doif whichPlayer == player thentable.remove(activePlayers, playerKey)playersLeft.Value = #activePlayerscheckPlayerCount()endendend
Connessione degli eventi e test
Per utilizzare la funzione appena creata, chiamala dall'interno dell'evento anonimo connesso all'evento Died del Giocatore.
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)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.
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.
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 localilocal function stopTimer()myTimer:stop()endlocal function timeUp()matchEnd:Fire(gameSettings.endStates.TimerUp)endPer interrompere il timer quando la partita finisce, connect the matchEnd event to stopTimer() .
-- Funzioni del modulofunction MatchManager.prepareGame()playerManager.sendPlayersToMatch()matchStart:Fire()endmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManagerProva 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 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
Script del 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
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