Matches können in einigen Bedingungen enden, einschließlich abgelaufender Timer oder eines einzelnen Spielers, der verlassen wird.
Verlorene Spieler verwalten
Derzeit erscheinen die besieigten Spieler in der Arena. Stattdessen schicken Sie sie zurück in die Lobby, um auf das nächste übereinstimmenzu warten.
- In PlayerManager erstellen Sie eine lokale Funktion namens respawnPlayerInLobby() . In dieser Funktion tun Sie gefolgte Profile:
- Setzen Sie die Eigenschaft RespawnLocation des Spieler:inauf die lobbySpawn.
- Laden Sie den Charakter mit Player:LoadCharacter() neu. Denken Sie daran, dass LoadCharacter() die Spieler bei ihrem Spawn wieder herstellt, indem sie alle Werkzeuge, die sie hatten, entfernt.
Verwendung von anonymen Funktionen
Anonyme Funktionen werden in fortgeschrittenen Skripts unter bestimmten Situationen häufig verwendet. Bevor Sie sie definieren, ist es wichtig zu verstehen, unter welcher Situation Ihr Skript möglicherweise stoßen wird.
Betrachte dies: Um die besieigten Spieler in die Lobby zu teleportieren, muss die Respawn-Funktion mit dem Died-Ereignis des Spieler:inverbunden sein. Es gibt jedoch ein Problem. Wenn Sie das Ereignis wie in der Vergangenheit mit dem Namen des Spielers verbinden, gibt es keine Möglichkeit, den Namen des Spielers aus dem Died-Ereignis zu erhalten. Das Skript benötigt diesen Namen, um einen besieigten Spieler von der Tabelle zu verfolgen, die aktive Spieler.
Um den Namen des Spielers zu erhalten, der das Abgelaufen-Ereignis ausgelöst hat, verwenden Sie eine anonyme Funktion. Anonyme Funktionen haben keine Namen und können direkt innerhalb von Connect() erstellt werden, anstatt separat.
Eine Beispielanonymfunktion ist unterhalb, die die Syntax anzeigt.
myPlayer.Died:Connect(function()
print(player)
end)
Codierung des gestorbenen Ereignisses
Für diese Funktion, wenn der Charakter eines Spieler:instirbt, wird die Funktion ausgelöst, die ihn respawns.
Um Zugriff auf das Died-Ereignis des Spieler:inzu erhalten, in PlayerManager > preparePlayer() , füge eine Variable für den Spieler:inhinzu.
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")endErstellen Sie eine anonyme Funktion, die sich mit dem Died-Ereignis verbindet. Starten Sie, indem Sie humanoid.Died:Connect() eingeben. Dann, innerhalb Connect() , tippe auf 1> function()1> und drücke 4> Enter 4> , um die automatische Vollständigung 7> beenden7> zu aktivieren und die zus
local humanoid = character:WaitForChild("Humanoid")humanoid.Died:Connect(function()end)In der anonymen Funktion, rufen Sie respawnPlayerInLobby() . Pass in player , eine Variable, die der Spieler bereit macht, um ein übereinstimmenzu betreten.
local humanoid = character:WaitForChild("Humanoid")humanoid.Died:Connect(function()respawnPlayerInLobby(player)end)Starten Sie einen Server und spielen Sie ein übereinstimmen. Testen Sie, dass wenn ein Spieler stirbt, dass er in der Lobby respawnen. Um Spieler zu besiegen, gehen Sie zu ihnen und verwenden Sie Ihre Waffe, bis Sie sicher sind, dass sie in der Lobby respawnen sind.
Beachten Sie, es gibt auch einige andere Möglichkeiten zum Testen, wenn gewünscht.
- Um einen Spieler:inzu töten, in der Server > Ausgabe-Fenster > Command Bar, kopieren und fügen Sie ein: workspace.Player1.Humanoid.Health = 0 . Drücken Sie Enter , um den Befehl auszuführen. Um andere Spieler zu entfernen, verwenden Sie Player2, Player3 usw.
- Das Festlegen von GameSettings > matchDuration kann Ihnen mehr Zeit geben, alle Spieler zu finden und zu eliminieren.
- Um schnellere Tests zu haben, ändern Sie GameSettings > minimumPlayers in eine kleinere Zahl, wie 2.
Ende des Spiels
Jetzt, da die besieigten Spieler respawnen, starten Sie mit der Arbeit an der Beendung des Spiels. Erinnern Sie sich, das MatchEnd-Ereignis zu erstellen? Es wird abgefeuert, wenn entweder der Timer abläuft oder ein Gewinner gefunden wird.
Um anderen Skripts mitzuteilen, dass die Spielbedingung beendet ist, erstellen Sie eine Tabelle mit Variablen für TimerUp und FoundWinner. Wenn das Spielende-Ereignis ausgelöst wird, wird es in einer Variable weitergegeben, damit andere Skripte reagieren können.
In GameSettings, erstellen Sie eine leere Modul-Tabelle namens endStates.
local GameSettings = {}-- Spiel variablenGameSettings.intermissionDuration = 5GameSettings.matchDuration = 10GameSettings.minimumPlayers = 2GameSettings.transitionTime = 5-- Mögliche Wege, wie das Spiel beendenkann.GameSettings.endStates = {}return GameSettingsErstellen Sie zwei Variablen mit dem Namen TimerUp und FoundWinner . Setzen Sie jede auf eine Zeichenfolge, die ihrem Namen entspricht. Diese Zeichenfolgen werden verwendet, um den Codeszu testen.
GameSettings.endStates = {TimerUp = "TimerUp",FoundWinner = "FoundWinner"}
Ende mit einem Timer
Wenn der Timer beendet ist, fire das Match End-Ereignis und sende die entsprechende Endzustands变量. Auf diese Weise können andere Skripte, die für dieses Ereignis lauschen, entsprechend antworten. Denken Sie daran, dass während Ereignifeuerzeichensignale gesendet werden, dass auch Daten senden können, die durch das Zuhören von Skripten erhalten werden, wie TimerUp oder FoundWinner .
In GameManager , in der Während wahr doLoop, finden Sie die Zeile matchEnd.Event:Wait() . Am Anfang der Zeile fügen Sie local endState = hinzu.
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()endUm sicherzustellen, dass der richtige Zustand erhalten wurde, füge eine druckende Anweisung hinzu, die endState enthält.
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 finden Sie timeUp() und entfernen die druck statement. Dann, um das Match-End-Ereignis zu feuern, geben Sie matchEnd:Fire() ein und passen Sie in 2>gameSettings.endSettings.timerUp2> ein.
-- Wertelocal displayValues = ReplicatedStorage:WaitForChild("DisplayValues")local timeLeft = displayValues:WaitForChild("TimeLeft")-- Erstellt ein neues Timer-Objekt, das verwendet wird, um die Match-Zeit zu verfolgen.local myTimer = timer.new()-- Lokale Funktionenlocal function timeUp()matchEnd:Fire(gameSettings.endStates.TimerUp)endTesten Sie ein übereinstimmen. Sobald der Timer ausgelaufen ist, stellen Sie sicher, dass die druck statement den strung in der TimerUp variablen enthält.
Troubleshooting-Tipps
An dieser Stelle wurde die Nachricht nicht angezeigt, versuchen Sie es mit einer der folgenden Optionen unten.
- Stellen Sie sicher, dass überall, wo die Variablen endzustellung aufgerufen werden, dass sie genau geschrieben sind, wie hier: gameSettings.endStates.TimerUp .
- Stellen Sie sicher, dass Sie : (Kolbenbetreiber) mit dem Fire() anstelle des Dot-Betreibers verwenden, wie in matchEnd:Fire().
Ein Gewinnendes Spiel codieren
Nächste, das Skript muss gewinnende Spieler identifizieren, verlierende Spieler entfernen und Reinigungen wie das Stoppen des TIMERS ausführen, um das Ergebnis zu sehen. Matches enden auch, wenn ein Spieler verlassen wird. Um zu sehen, ob die FoundWinner-Bedingung erfüllt ist, benötigst du eine Funktion, die die Nummer in der Tabelle verfolgt, die Spieler in einem übereinstimmenanzeigt.
Spieleranzahl überprüfen
Die Matches werden enden, wenn nur ein Spieler übrig bleibt. Um dies zu überprüfen, muss das Skript die Spieler in einer Runde verfolgen. Sobald ein Spieler übrig bleibt, kann ein Gewinner zugewiesen werden.
In PlayerManager definieren Sie die folgenden Variablen:
- ModuleScripts-Ordner
- GameSettings-Modul - Wird verwendet, um Ziel变ablen zuzugreifen
- Events-Ordner und das MatchEnd-Ereignis - Feuert das Ereignis
local PlayerManager = {}-- Dienstelocal Players = game:GetService("Players")local ServerStorage = game:GetService("ServerStorage")local ReplicatedStorage = game:GetService("ReplicatedStorage")-- Modulelocal moduleScripts = ServerStorage:WaitForChild("ModuleScripts")local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))-- Ereignisselocal events = ServerStorage:WaitForChild("Events")local matchEnd = events:WaitForChild("MatchEnd")Über respawnPlayerInLobby() , füge eine neue lokale Funktion hinzu, die checkPlayerCount() heißt.
-- Spieler Variableslocal activePlayers = {}local playerWeapon = ServerStorage.Weaponlocal function checkPlayerCount()endlocal function respawnPlayerInLobby(player)In dieser Funktion verwenden Sie ein if dann Anweisung, um nach einem Gewinner zu suchen. In dieser Anweisung:
- Überprüfen Sie, ob die Größe der activePlayers Tabelle 1 ist.
- Wenn so, feuere matchEnd und passiere in gameSettings.endStates.FoundWinner .
local function checkPlayerCount()if #activePlayers == 1 thenmatchEnd:Fire(gameSettings.endStates.FoundWinner)endend
Einen Spieler entfernen
Eine genaue Anzahl kann nicht gehalten werden, es sei denn, Spieler werden entfernt. Wenn ein Spieler besiegt ist, behalten Sie eine genaue Anzahl von Spielern, indem Sie sie aus der Spieler-Tabelle entfernen. Dann überprüfen Sie die Größe der aktiven Spieler-Tabelle, um zu sehen, ob es einen Gewinner gibt.
Unter checkPlayerCount() , erstellen Sie eine neue lokale Funktion namens removeActivePlayer() mit einem Parameter namens player .
local function checkPlayerCount()if #activePlayers == 1 thenmatchEnd:Fire(gameSettings.endStates.FoundWinner)endendlocal function removeActivePlayer(player)endUm den Spieler in der activePlayers Tabelle zu finden, durchlaufen Sie sie mit einem for Loop. Dann fügen Sie eine if Anweisung hinzu, die ausgeführt wird, wenn ein Spieler den Namen passend findet.
local function removeActivePlayer(player)for playerKey, whichPlayer in activePlayers doif whichPlayer == player thenendendendUm den Spieler:inzu entfernen, in der if-Anweisung:
- Rufen Sie table.remove() . In den Klammern übergeben Sie activePlayers , die Tabelle, in die Sie schauen, und playerKey - den Spieler von der Tabelle zu entfernen.
- Setzen Sie den Wert des Objekts playersLeft auf #activePlayers.
- Überprüfen Sie einen gewinnenden Spieler, indem Sie checkPlayerCount() ausführen.
local function removeActivePlayer(player)for playerKey, whichPlayer in activePlayers doif whichPlayer == player thentable.remove(activePlayers, playerKey)playersLeft.Value = #activePlayerscheckPlayerCount()endendend
Verbindung von Ereignissen und Testen
Um die gerade erstellte Funktion zu verwenden, rufen Sie sie von innerhalb des anonymen Funktionsaufrufs, der dem Spieler:inDied -Ereignis zugewiesen ist, auf.
Finden Sie preparePlayer() . In der anonymen Funktion mit der Died-Ereignisverbindung rufen Sie removeActivePlayer() . Dann, übergeben Sie den Spieler als Parameter.
humanoid.Died:Connect(function()respawnPlayerInLobby(player)removeActivePlayer(player)end)Um zu sehen, ob ein gewinnender Spieler gefunden wird, starten Sie einen Test-Server . Wenn es nur einen Spieler übrig gibt, sollten Sie FoundWinner im Ausgabe-Fenster sehen.
Teste weiter und lass das Spiel beenden. Beachte, wie ein neues Spiel beginnt, erscheint ein Fehler im Ausgabefenster:
Dieser Fehler ist, weil der Timer nicht gestoppt wurde, was in der nächsten Sektion behoben wird.
Stoppen des Tinners
Wenn ein Match mit einem gewinnenden Spieler:inendet, sollte der Timer auch stoppen. Um den Timer vor Ablauf der Zeit zu stoppen, muss der Timer jedes Mal stoppen, wenn das Match-Endereignis ausgelöst wird. Dies ist einer der Vorteile der Erstellung von Ereignissen. Sie können in mehreren Situationen wiederverwendet werden, um Skript-Verhältnisse und Effekte zu scripten.
In MatchManager erstellen Sie eine neue lokale Funktion namens stopTimer() . Dans, type myTimer:stop() um den Timer zu stoppen.
-- Erstellt ein neues Timer-Objekt, das verwendet wird, um die Match-Zeit zu verfolgen.local myTimer = timer.new()-- Lokale Funktionenlocal function stopTimer()myTimer:stop()endlocal function timeUp()matchEnd:Fire(gameSettings.endStates.TimerUp)endUm den Timer zu stoppen, wenn das Spiel beendet ist, verbinden Sie das MatchEnd-Ereignis mit stopTimer() .
-- Modul-Funktionenfunction MatchManager.prepareGame()playerManager.sendPlayersToMatch()matchStart:Fire()endmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManagerTesten , dass der vorherige Fehler nicht mehr angezeigt wird, indem ein Server neu startet. Eliminiere alle, aber ein Spieler, und warte dann einige Sekunden, sobald das Spiel beendet ist.
Nächste Schritte
Während die beiden Gewinnbedingungen fertig sind, gibt es noch einige Aufgaben, die das Spiel-Loop beenden. Zum Instanzwird der gewinnende Spieler nie in die Lobby teleportiert. In der nächsten Lektion zeigen Sie, wie das Spiel für die Spieler beendet und das Spiel neu startet, um das gesamte Loop zu beenden.
Abgeschlossene Skripte
Dies sind abgeschlossene Skripte, um deine Arbeit zu überprüfen.
SpielerManager-Skript
local PlayerManager = {}
-- Dienste
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Module
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
-- Ereignisse
local events = ServerStorage:WaitForChild("Events")
local matchEnd = events:WaitForChild("MatchEnd")
-- Karten- Variablen
local lobbySpawn = workspace.Lobby.StartSpawn
local arenaMap = workspace.Arena
local spawnLocations = arenaMap.SpawnLocations
-- Werte
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local playersLeft = displayValues:WaitForChild("PlayersLeft")
-- Spieler Variables
local activePlayers = {}
local playerWeapon = ServerStorage.Weapon
-- Lokale Funktionen
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
-- Modul-Funktionen
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
-- Ereignisse
Players.PlayerAdded:Connect(onPlayerJoin)
return PlayerManager
Spieleinstellungen-Skrip
local GameSettings = {}-- Spiel variablenGameSettings.intermissionDuration = 5GameSettings.matchDuration = 10GameSettings.minimumPlayers = 2GameSettings.transitionTime = 5-- Mögliche Wege, wie das Spiel beendenkann.GameSettings.endStates = {TimerUp = "TimerUp",FoundWinner = "FoundWinner"}return GameSettings
GameManager-Skript
-- Dienstelocal ServerStorage = game:GetService("ServerStorage")local Players = game:GetService("Players")-- Modul-Scriptslocal moduleScripts = ServerStorage:WaitForChild("ModuleScripts")local matchManager = require(moduleScripts:WaitForChild("MatchManager"))local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))local displayManager = require(moduleScripts:WaitForChild("DisplayManager"))-- Ereignisselocal 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
MatchManager-Skript
local MatchManager = {}
-- Dienste
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Modul-Scripts
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local playerManager = require(moduleScripts:WaitForChild("PlayerManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
local timer = require(moduleScripts:WaitForChild("Timer"))
-- Ereignisse
local events = ServerStorage:WaitForChild("Events")
local matchStart = events:WaitForChild("MatchStart")
local matchEnd = events:WaitForChild("MatchEnd")
-- Werte
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local timeLeft = displayValues:WaitForChild("TimeLeft")
-- Erstellt ein neues Timer-Objekt, das verwendet wird, um die Match-Zeit zu verfolgen.
local myTimer = timer.new()
-- Lokale Funktionen
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
-- Durch das Hinzufügen von +1 wird sichergestellt, dass der Timer-Anzeige 1 statt 0 endet.
timeLeft.Value = (math.floor(myTimer:getTimeLeft() + 1))
-- Durch das Festlegen der Wartezeit bietet es eine präzisere Loop-Funktion
task.wait()
end
end
-- Modul-Funktionen
function MatchManager.prepareGame()
playerManager.sendPlayersToMatch()
matchStart:Fire()
end
matchStart.Event:Connect(startTimer)
matchEnd.Event:Connect(stopTimer)
return MatchManager