Spiele können mit einigen Bedingungen enden, einschließlich der Tatsache, dass Timer ablaufen oder ein einzelner Spieler verlassen wird.
Besiegte Spieler verwalten
Im Moment respawnen besiegte Spieler in der Arena. Stattdessen schicke sie zurück in die Lobby, um auf das nächste übereinstimmenzu warten.
- Erstellen Sie in PlayerManager eine lokale Funktion mit dem Namen respawnPlayerInLobby(). In dieser Funktion tun Sie gefolgte Profile:
- Setze die RespawnLocation-Eigenschaft des Spieler:inauf lobbySpawn.
- Lade den Charakter mit Player:LoadCharacter() neu. Denke daran, LoadCharacter() erstellt den Spieler bei seinem Spawn und entfernt alle Werkzeuge, die er hatte.
Verwende anonyme Funktionen
Anonyme Funktionen werden häufig in fortgeschrittenen Skripten unter bestimmten Situationen verwendet.Bevor du sie definierst, ist es wichtig, eine Situation zu verstehen, mit der dein Skript konfrontiert werden kann.
Betrachte das: Um besiegte Spieler in die Lobby zu teleportieren, muss die Respawn-Funktion mit dem Died-Ereignis des Spieler:inverbunden sein.Es gibt jedoch ein Problem.Wenn du das Ereignis wie in der Vergangenheit verbindest, gibt es keine Möglichkeit, den Namen des Spielers aus dem Ereignis "Tot" zu erhalten.Das Skript benötigt diesen Namen, um einen besiegelten Spieler von der Tabelle zu entfernen, die aktive Spieler verfolgt.
Um den Namen des Spielers zu erhalten, der das Ereignis Tod ausgelöst hat, verwende eine anonyme Funktion. Anonyme Funktionen haben keine Namen und können direkt innerhalb von Connect() erstellt werden, anstatt separat.
Eine Beispielanonyme Funktion ist unten, die die Syntax zeigt.
myPlayer.Died:Connect(function()
print(player)
end)
Code das verstorbene Ereignis
Für diese Funktion wird immer dann ausgelöst, wenn der Charakter eines Spieler:instirbt, die Funktion, die ihn wiederbelebt.
Um Zugriff auf das Ereignis Died des Spieler:inzu erhalten, in PlayerManager > preparePlayer() , füge eine Variable für den Humanoid des 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")endErstelle eine anonyme Funktion, die sich mit dem Ereignis Tod verbindet.Beginnen Sie, indem Sie humanoid.Died:Connect() eingeben.Dann, innerhalb Connect() , geben Sie function() ein, drücken Sie Enter , um end automatisch zu vervollständigen, und löschen Sie die zusätzliche Klammer.
local humanoid = character:WaitForChild("Humanoid")humanoid.Died:Connect(function()end)In der anonymen Funktion rufen Sie respawnPlayerInLobby() auf. Geben Sie player ein, eine Variable, die den Spieler bereit macht, ein übereinstimmenzu betreten.
local humanoid = character:WaitForChild("Humanoid")humanoid.Died:Connect(function()respawnPlayerInLobby(player)end)Starte einen Server und spiele ein übereinstimmen.Teste, dass wenn ein Spieler stirbt, er in der Lobby wiederbelebt wird.Um Spieler zu besiegen, gehe auf sie zu und benutze deine Waffe, bis du bestätigen kannst, dass sie in der Lobby respawned sind.
Angriff auf Spieler2 Spieler2 in der Lobby nach der Wiederbelebung
Beachten Sie, es gibt auch einige verschiedene Möglichkeiten zum Testen, wenn gewünscht.
- Um einen Spieler:inzu töten, kopiere und füge im Server > Ausgabe-Fenster > Befehlsleiste ein: workspace.Player1.Humanoid.Health = 0 .Drücken Sie Enter, um den Befehl auszuführen.Um andere Spieler zu entfernen, verwende Player2, Player3 usw.
- Die Einstellung von GameSettings > zu einer längeren Zeit kann Ihnen mehr Zeit geben, um alle Spieler zu finden und auszuschalten.
- Um schnellere Tests durchzuführen, ändere GameSettings > minimumPlayers auf kleinere Zahl, wie 2.
Beende das Spiel
Jetzt, da besiegte Spieler respawnen, beginne mit der Arbeit am Beenden des Spiels.Erinnerst du dich an die Erstellung des MatchEnd-Events? Es wird abgefeuert, wenn entweder der Timer abläuft oder ein Gewinner gefunden wird.
Um anderen Skripten mitzuteilen, unter welcher Bedingung das Spiel beendet wurde, erstelle eine Tabelle mit Variablen für TimerUp und FoundWinner.Wenn das Match-End-Ereignis ausgelöst wird, wird es in einer Variable übergeben, damit andere Skripte antworten können.
Erstelle in den GameSettings einen leeren Modul-Tab mit dem Namen endStates.
local GameSettings = {}-- SpielvariablenGameSettings.intermissionDuration = 5GameSettings.matchDuration = 10GameSettings.minimumPlayers = 2GameSettings.transitionTime = 5-- Mögliche Wege, wie das Spiel beendenkann.GameSettings.endStates = {}return GameSettingsErstellen Sie zwei Variablen mit den Namen TimerUp und FoundWinner. Setzen Sie jede auf eine Zeichenfolge, die ihrem Namen entspricht. Diese Zeichenfolgen werden zum Testen des Codes verwendet.
GameSettings.endStates = {TimerUp = "TimerUp",FoundWinner = "FoundWinner"}
Beenden mit einem Timer
Wenn der Timer endet, feuere das Match-End-Ereignis ab und sende die passende Endzustandsvariable.So können andere Skripte, die auf dieses Ereignis hören, entsprechend reagieren.Denken Sie daran, dass während Ereignisse Signale abfeuern, dass auch Daten senden kann, die von Listening-Skripten empfangen werden, wie TimerUp oder FoundWinner.
In GameManager , in der while true do Schleife, finden Sie die Zeile matchEnd.Event:Wait(). Am Beginn 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 zu bestätigen, dass der korrekte Zustand empfangen wurde, füge eine Druckausdruck hinzu, der 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 Druckausgabe.Dann, um das Endereignis des Spiels abzufeuern, geben Sie matchEnd:Fire() ein und übergeben Sie gameSettings.endStates.TimerUp.
-- Wertelocal displayValues = ReplicatedStorage:WaitForChild("DisplayValues")local timeLeft = displayValues:WaitForChild("TimeLeft")-- Erstellt ein neues Timer-Objekt, das verwendet wird, um die Spielzeit zu verfolgen.local myTimer = timer.new()-- Lokale Funktionenlocal function timeUp()matchEnd:Fire(gameSettings.endStates.TimerUp)endTeste ein übereinstimmen. Sobald der Timer abgelaufen ist, überprüfe, ob die Druck statement den String enthält, der in der TimerUp Variable gespeichert ist.
Problemlösungstipps
An diesem Punkt wurde die Nachricht nicht angezeigt, versuchen Sie eine der folgenden Optionen.
- Überprüfe, dass überall, wo die Endzustandsvariablen aufgerufen werden, genau geschrieben werden, wie hier: gameSettings.endStates.TimerUp .
- Stellen Sie sicher, :(Kolonnenbetreiber) mit dem Fire() anstelle des Punktoпераators zu verwenden, wie in matchEnd:Fire() .
Kodiere ein gewinnendes übereinstimmen
Als Nächstes muss das Skript gewinnende Spieler identifizieren, verlorene Spieler entfernen und Reinigungsaufgaben wie das Beenden des Timers ausführen.Spiele enden auch, wenn ein Spieler übrig bleibt.Um zu sehen, ob die Bedingung FoundWinner erfüllt ist, benötigen Sie eine Funktion, die die in der Tabelle verbleibende Anzahl von Spielern in einem übereinstimmenüberprüft.
Spieleranzahl überprüfen
Spiele enden, wenn nur ein Spieler übrig ist.Um dies zu überprüfen, muss das Skript die Spieler in einer Runde verfolgen.Sobald ein Spieler verlassen ist, kann ein Gewinner zugewiesen werden.
In PlayerManager definieren Sie die folgenden Variablen:
- Ordner ModulScripts
- GameSettings-Modul - Wird verwendet, um Endzustandsvariablen zuzugreifen
- Veranstaltungsordner und das MatchEnd-Ereignis - Feuerevent
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 mit dem Namen checkPlayerCount() hinzu.
-- Spielervariablenlocal activePlayers = {}local playerWeapon = ServerStorage.Weaponlocal function checkPlayerCount()endlocal function respawnPlayerInLobby(player)Innerhalb dieser Funktion verwende ein if dann-Statement, um nach einem Gewinner zu suchen. In dieser Aussage:
- Überprüfe, ob die Größe der activePlayers Tabelle 1 ist.
- Wenn ja, feuere matchEnd ab und gib gameSettings.endStates.FoundWinner ein.
local function checkPlayerCount()if #activePlayers == 1 thenmatchEnd:Fire(gameSettings.endStates.FoundWinner)endend
Spieler:inentfernen
Eine genaue Zählung kann nicht beibehalten werden, es sei denn, Spieler werden entfernt.Wenn ein Spieler besiegt wird, halte eine genaue Spieleranzahl aufrecht, indem du ihn vom Spieler-Tisch entfernst.Überprüfe dann die Größe des aktiven Spielertisches, um zu sehen, ob es einen Gewinner gibt.
Unter checkPlayerCount(), erstelle eine neue lokale Funktion mit dem Namen 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, iteriere durch sie mit einer for Schleife.Füge dann eine if-Aussage hinzu, die ausgeführt wird, wenn ein Spieler mit dem Namen, der in die Funktion übergeben wird, gefunden wird.
local function removeActivePlayer(player)for playerKey, whichPlayer in activePlayers doif whichPlayer == player thenendendendUm den Spieler:inzu entfernen, in der if- statement:
- Rufen Sie table.remove() an. Im Inneren der Klammern geben Sie activePlayers ein, die Tabelle, die angesehen werden soll, und playerKey - den Spieler, den Sie von der Tabelle entfernen müssen.
- Setze den Wert des playersLeft Objekts auf #activePlayers.
- Überprüfe einen siegreichen Spieler, indem du checkPlayerCount() ausführst.
local function removeActivePlayer(player)for playerKey, whichPlayer in activePlayers doif whichPlayer == player thentable.remove(activePlayers, playerKey)playersLeft.Value = #activePlayerscheckPlayerCount()endendend
Verbinden von Ereignissen und Testen
Um die gerade erstellte Funktion zu verwenden, rufe sie von der anonymen Funktion aus, die mit dem Died-Ereignis des Spieler:inverbunden ist.
Finde preparePlayer() . In der anonymen Funktion mit der Verbindung zum Ereignis Tod, rufe removeActivePlayer() auf. Dann übermittle den Spieler als Parameter.
humanoid.Died:Connect(function()respawnPlayerInLobby(player)removeActivePlayer(player)end)Um zu sehen, ob ein Gewinner gefunden wird, starten Sie einen Testserver .Wenn nur ein Spieler übrig ist, solltest du FoundWinner im Ausgabe-Fenster sehen.
Fortfahren Sie mit den Tests und lassen Sie das Spiel beenden. Beachten Sie, wenn ein neues Spiel beginnt, erscheint ein Fehler im Ausgabe-Fenster:
Dieser Fehler tritt auf, weil der Timer nicht angehalten wurde, was im nächsten Abschnitt behoben wird.
Stoppe den Timer
Wann immer ein Spiel mit einem siegreichen Spieler:inendet, sollte auch die Timer stoppen.Um den Timer zu stoppen, bevor die Zeit abläuft, lass den Timer stoppen, wenn das Match-End-Ereignis ausgelöst wird.Dies ist einer der Vorteile der Erstellung von Ereignissen.Sie können in mehreren Situationen wiederverwendet werden, um Skript-Ursache- und -Wirkungsbeziehungen zu skriptieren.
Erstellen Sie in MatchManager eine neue lokale Funktion mit dem Namen stopTimer(). Im Inneren geben Sie myTimer:stop() ein, um den Timer anzuhalten.
-- Erstellt ein neues Timer-Objekt, das verwendet wird, um die Spielzeit 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 endet, verbinden Sie das matchEnd-Ereignis mit stopTimer().
-- Modulfunktionenfunction MatchManager.prepareGame()playerManager.sendPlayersToMatch()matchStart:Fire()endmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManagerTest , dass der vorherige Fehler nicht mehr auftaucht, indem du einen Server startest.Eliminiere alle, aber einen Spieler und warte dann ein paar Sekunden, nachdem das Spiel beendet ist.
Nächste Schritte
Während die beiden Gewinnbedingungen abgeschlossen sind, bleiben noch einige Aufgaben übrig, um die Spielschleife abzuschließen.Zum Instanzwird der gewinnende Spieler niemals in die Lobby teleportiert.In der nächsten Lektion zeigst du an, wie das Spiel für Spieler beendet wurde und setzt das Spiel zurück, um schließlich die gesamte Schleife abzuschließen.
Abgeschlossene Skripte
Im Folgenden sind abgeschlossene Skripte, um deine Arbeit zu überprüfen.
Skript, das. PL: die Skripts
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")
-- Kartenvariablen
local lobbySpawn = workspace.Lobby.StartSpawn
local arenaMap = workspace.Arena
local spawnLocations = arenaMap.SpawnLocations
-- Werte
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local playersLeft = displayValues:WaitForChild("PlayersLeft")
-- Spielervariablen
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
-- Modulfunktionen
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
Skript, das. PL: die Skripts
local GameSettings = {}-- SpielvariablenGameSettings.intermissionDuration = 5GameSettings.matchDuration = 10GameSettings.minimumPlayers = 2GameSettings.transitionTime = 5-- Mögliche Wege, wie das Spiel beendenkann.GameSettings.endStates = {TimerUp = "TimerUp",FoundWinner = "FoundWinner"}return GameSettings
Skript, das. PL: die Skripts
-- Dienstelocal ServerStorage = game:GetService("ServerStorage")local Players = game:GetService("Players")-- Modul-Skriptelocal 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
Skript, das. PL: die Skripts
local MatchManager = {}
-- Dienste
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Modul-Skripte
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 Spielzeit 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
-- Das Hinzufügen von +1 stellt sicher, dass die Timeranzeige bei 1 statt bei 0 endet.
timeLeft.Value = (myTimer:getTimeLeft() + 1) // 1
-- Durch das Nicht festlegen der Zeit für die Wartezeit bietet es genauere Schleifen
task.wait()
end
end
-- Modulfunktionen
function MatchManager.prepareGame()
playerManager.sendPlayersToMatch()
matchStart:Fire()
end
matchStart.Event:Connect(startTimer)
matchEnd.Event:Connect(stopTimer)
return MatchManager