Endende Spiele

*Dieser Inhalt wurde mit KI (Beta) übersetzt und kann Fehler enthalten. Um diese Seite auf Englisch zu sehen, klicke hier.

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.

  1. 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.

  1. 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 = 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. Erstellen 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)
  3. 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)
  4. 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.

    Spieler2 attackieren
    Spieler2 in der Lobby nach dem Respawnen

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.

  1. In GameSettings, erstellen Sie eine leere Modul-Tabelle namens endStates.


    local GameSettings = {}
    -- Spiel variablen
    GameSettings.intermissionDuration = 5
    GameSettings.matchDuration = 10
    GameSettings.minimumPlayers = 2
    GameSettings.transitionTime = 5
    -- Mögliche Wege, wie das Spiel beendenkann.
    GameSettings.endStates = {
    }
    return GameSettings
  2. Erstellen 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 .

  1. 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 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. Um sicherzustellen, dass der richtige Zustand erhalten wurde, füge eine druckende Anweisung hinzu, die endState enthält.


    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 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.


    -- 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 timeUp()
    matchEnd:Fire(gameSettings.endStates.TimerUp)
    end
  4. Testen 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.

  1. 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 = {}
    -- 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")
  2. Über respawnPlayerInLobby() , füge eine neue lokale Funktion hinzu, die checkPlayerCount() heißt.


    -- Spieler Variables
    local activePlayers = {}
    local playerWeapon = ServerStorage.Weapon
    local function checkPlayerCount()
    end
    local function respawnPlayerInLobby(player)
  3. 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 then
    matchEnd:Fire(gameSettings.endStates.FoundWinner)
    end
    end

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.

  1. Unter checkPlayerCount() , erstellen Sie eine neue lokale Funktion namens removeActivePlayer() mit einem Parameter namens player .


    local function checkPlayerCount()
    if #activePlayers == 1 then
    matchEnd:Fire(gameSettings.endStates.FoundWinner)
    end
    end
    local function removeActivePlayer(player)
    end
  2. Um 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 do
    if whichPlayer == player then
    end
    end
    end
  3. Um 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 do
    if whichPlayer == player then
    table.remove(activePlayers, playerKey)
    playersLeft.Value = #activePlayers
    checkPlayerCount()
    end
    end
    end

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.

  1. 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)
  2. 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.

  3. 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.

  1. 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 Funktionen
    local function stopTimer()
    myTimer:stop()
    end
    local function timeUp()
    matchEnd:Fire(gameSettings.endStates.TimerUp)
    end
  2. Um den Timer zu stoppen, wenn das Spiel beendet ist, verbinden Sie das MatchEnd-Ereignis mit stopTimer() .


    -- Modul-Funktionen
    function MatchManager.prepareGame()
    playerManager.sendPlayersToMatch()
    matchStart:Fire()
    end
    matchStart.Event:Connect(startTimer)
    matchEnd.Event:Connect(stopTimer)
    return MatchManager
  3. Testen , 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 variablen
GameSettings.intermissionDuration = 5
GameSettings.matchDuration = 10
GameSettings.minimumPlayers = 2
GameSettings.transitionTime = 5
-- Mögliche Wege, wie das Spiel beendenkann.
GameSettings.endStates = {
TimerUp = "TimerUp",
FoundWinner = "FoundWinner"
}
return GameSettings

GameManager-Skript


-- Dienste
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
-- Modul-Scripts
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local matchManager = require(moduleScripts:WaitForChild("MatchManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
local displayManager = require(moduleScripts:WaitForChild("DisplayManager"))
-- Ereignisse
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

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