Matchs à fin

*Ce contenu est traduit en utilisant l'IA (Beta) et peut contenir des erreurs. Pour consulter cette page en anglais, clique ici.

Les matchs peuvent se terminer dans quelques conditions, y compris les temps d'expiration des timers ou le fait qu'un seul joueur soit resté.

Gérer les joueurs vaincus

En ce moment, les joueurs vaincus réapparaissent dans l'arène. À la place, envoyez-les à nouveau dans le lobby pour attendre le prochain correspondre.

  1. Dans PlayerManager, créez une fonction locale nommée respawnPlayerInLobby() . Dans cette fonction, faites les choses suivre:
  • Définir la propriété RespawnLocation du joueur à laquelle le lobbySpawn.
  • Rechargez le personnage avec Player:LoadCharacter() . N'oubliez pas, LoadCharacter() recréé le joueur à leur point d'apparition, en supprimant les outils qu'ils avaient.

Utilisation des fonctions anonymes

Les fonctions anonymes sont couramment utilisées dans les scripts avancés sous des situations spécifiques. Avant de les définir, il est important de comprendre une situation dans laquelle votre script peut se trouver.

Considérez ceci : Pour téléporter les joueurs vaincus dans le lobby, la fonction de respawn doit être connectée à l'événement Died du joueur. Il y a un problème cependant. Si vous connectez l'événement comme nous l'avons fait dans le passé, il n'y a pas de manière d'obtenir le nom du joueur de l'événement Died. Le script a besoin de ce nom pour supprimer un joueur vaincu de la table de traçage des joueurs actifs.

Pour obtenir le nom du joueur qui a déclenché l'événement mortel, utilisez une fonction anonyme. Les fonctions anonymes ne ont pas de noms, et peuvent être créées directement dans Connect() plutôt que séparément.

Une fonction anonyme de例 est ci-dessous qui montre la syntaxe.


myPlayer.Died:Connect(function()
print(player)
end)

Codage de l'événement mort

Pour cette fonction, chaque fois qu'un personnage d'un joueur meurt, il déclenchera la fonction qui les réapparaît.

  1. Pour obtenir l'accès à l'événement Died du joueur, dans PlayerManager > preparePlayer(), ajoutez une variable pour le humanoid du joueur.


    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. Créez une fonction anonyme qui se connecte à l'événement Died. Commencez par saisir humanoid.Died:Connect() . Puis, à l'intérieur Connect() , tapez 1> function()1> , appuyez sur 4> Entrer4> pour autocompléter 7> terminer7> et supprimez la parenthèse supplémentaire.


    local humanoid = character:WaitForChild("Humanoid")
    humanoid.Died:Connect(function()
    end)
  3. Dans la fonction anonyme, appelez respawnPlayerInLobby() . Pass in player, une variable stockant le joueur se préparant à entrer dans un correspondre.


    local humanoid = character:WaitForChild("Humanoid")
    humanoid.Died:Connect(function()
    respawnPlayerInLobby(player)
    end)
  4. Démarrez un serveur et jouez un correspondre. Testez que lorsqu'un joueur meurt, il réapparaît dans le lobby. Pour vaincre les joueurs, approchez-vous-y et utilisez votre arme jusqu'à ce que vous puissiez confirmer qu'ils sont réapparus dans le lobby.

    Attaquer le joueur 2
    Joueur 2 dans Lobby après la réapparition

Notez, il y a aussi des méthodes de test différentes si vous le souhaitez.

  • Pour tuer un joueur, dans la fenêtre de sortie du serveur > barre de commande > commande, copiez et collez : workspace.Player1.Humanoid.Health = 0 . Appuyez sur Entrer pour exécuter la commande. Pour supprimer d'autres joueurs, utilisez Player2, Player3, etc.
  • Définir GameSettings > matchDuration à un temps plus long peut vous donner plus de temps pour trouver et éliminer tous les joueurs.
  • Pour avoir des tests plus rapides, changez GameSettings > minimumPlayers à un nombre plus petit, comme 2.

Fin de la partie

Maintenant que les joueurs vaincus réapparaissent, commencez à travailler sur la fin du jeu. Souvenez-vous de créer l'événement MatchEnd ? Il sera déclenché lorsque le temps écoulé sera écoulé ou qu'un gagnant sera trouvé.

Pour dire aux autres scripts qui ont terminé le jeu, créez une table avec des variables pour TimerUp et FoundWinner. Lorsque l'événement de fin de match se déclenche, il passe en variable afin que d'autres scripts puissent répondre.

  1. Dans GameSettings, créez une table de module vide nommée endStates .


    local GameSettings = {}
    -- Variables de jeu
    GameSettings.intermissionDuration = 5
    GameSettings.matchDuration = 10
    GameSettings.minimumPlayers = 2
    GameSettings.transitionTime = 5
    -- Possibles façons que le jeu puisse se terminer.
    GameSettings.endStates = {
    }
    return GameSettings
  2. Créez deux variables nommées TimerUp et FoundWinner . Chacun d'eux sera configuré pour correspondre à leur nom. Ces chaînes seront utilisées pour tester le code.


GameSettings.endStates = {
TimerUp = "TimerUp",
FoundWinner = "FoundWinner"
}

Fin avec un Timer

Lorsque le minuteur se termine, firez l'événement Match End et envoyez la variable d'état de fin correspondante. De cette façon, d'autres scripts qui écoutent cet événement peuvent répondre en conséquence. N'oubliez pas que, pendant que les événements firent des signaux, cela peut également envoyer des données reçues en écoutant les scripts, comme TimerUp ou FoundWinner.

  1. Dans GameManager , dans le while true do loop, trouvez la ligne matchEnd.Event:Wait(). Au début de la ligne, ajoutez local endState = .


    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. Pour confirmer que l'état correct a été reçu, ajoutez une déclaration d'impression comprenant endState .


    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. Dans MatchManager, trouvez timeUp() et supprimer la déclaration d'impression. Puis, pour lancer l'événement de fin de match, tapez matchEnd:Fire() et donnez 1> gameSettings.endSettings.timerUp1> .


    -- Valeurs
    local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
    local timeLeft = displayValues:WaitForChild("TimeLeft")
    -- Crée un nouvel objet de minuterie à utiliser pour suivre le temps du match.
    local myTimer = timer.new()
    -- Fonctions locales
    local function timeUp()
    matchEnd:Fire(gameSettings.endStates.TimerUp)
    end
  4. Testez un correspondre. Une fois que le minuteur s'est écoulé, vérifiez que la déclaration d'impression inclut la chaîne stockée dans la variable TimerUp.

Conseils de débogage

À ce moment, le message n'a pas été affiché, essayez l'une des options suivantes.

  • Vérifiez que, où que se trouvent les variables d'état de fin, qu'elles sont écrites exactement, comme ici : gameSettings.endStates.TimerUp .
  • Assurez-vous d'utiliser : (opérateur de colonne) avec le Fire() au lieu de l'opérateur de point, comme dans matchEnd:Fire().

Programmer un match gagnant

Ensuite, le script doit identifier les joueurs gagnants, supprimer les joueurs perdants et exécuter un nettoyage comme arrêter le minuteur. Les matchs s'arrêteront également si un joueur est quitté. Pour voir si la condition FoundWinner est remplie, vous aurez besoin d'une fonction qui vérifie le nombre restant dans la table suivant les joueurs dans un correspondre.

Vérification du nombre de joueurs

Les matchs se termineront si il ne reste qu'un seul joueur. Pour vérifier cela, le script doit suivre les joueurs dans une manche. Une fois qu'un joueur est parti, un gagnant peut être attribué.

  1. Définissez dans PlayerManager les variables suivantes :

    • DossierModuleScripts
    • Module GameSettings - Utilisé pour accéder aux variables d'état de fin
    • Dossier d'événements et l'événement MatchEnd - Fires l'événement

    local PlayerManager = {}
    -- Services
    local Players = game:GetService("Players")
    local ServerStorage = game:GetService("ServerStorage")
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    -- Modules
    local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
    local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
    -- Événements
    local events = ServerStorage:WaitForChild("Events")
    local matchEnd = events:WaitForChild("MatchEnd")
  2. Au-dessus de respawnPlayerInLobby(), ajoutez une nouvelle fonction locale nommée checkPlayerCount() .


    -- Variables du joueur
    local activePlayers = {}
    local playerWeapon = ServerStorage.Weapon
    local function checkPlayerCount()
    end
    local function respawnPlayerInLobby(player)
  3. Dans cette fonction, utilisez une if then statement pour vérifier un gagnant. Dans cette déclaration :

    • Vérifiez si la taille de la table activePlayers est 1.
    • Si oui, tirez matchEnd et donnez gameSettings.endStates.FoundWinner .

    local function checkPlayerCount()
    if #activePlayers == 1 then
    matchEnd:Fire(gameSettings.endStates.FoundWinner)
    end
    end

Suppression d'un joueur

Un compte exact ne peut pas être gardé à moins que les joueurs ne soient supprimés. Lorsqu'un joueur est vaincu, gardez un nombre de joueurs exact en le retirant de la table des joueurs. Puis, vérifiez la taille de la table des joueurs actifs pour voir s'il y a un gagnant.

  1. Sous checkPlayerCount() , créez une nouvelle fonction locale nommée removeActivePlayer() avec un paramètre nommé player .


    local function checkPlayerCount()
    if #activePlayers == 1 then
    matchEnd:Fire(gameSettings.endStates.FoundWinner)
    end
    end
    local function removeActivePlayer(player)
    end
  2. Pour trouver le joueur dans la table activePlayers, itérez-vous à travers elle en utilisant un boucle for. Ensuite, ajoutez une déclaration if qui s'exécute si un joueur correspondant au nom s'est trouvé dans la fonction.


    local function removeActivePlayer(player)
    for playerKey, whichPlayer in activePlayers do
    if whichPlayer == player then
    end
    end
    end
  3. Pour supprimer le joueur, dans la déclaration if :

    • Appeler table.remove() . Dans les parenthèses, passez en activePlayers , la table à laquelle vous regardez, et playerKey - le joueur à enlever de la table.
    • Définissez la valeur de l'objet playersLeft à #activePlayers.
    • Vérifiez un joueur gagnant en exécutant checkPlayerCount() .

    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

Connexion d'événements et test

Pour utiliser la fonction vient de créer, appelez-la à partir de l'événement anonyme connecté au joueur's Died .

  1. Trouvez preparePlayer() . Dans la fonction anonyme avec la connexion d'événement Died, appelez removeActivePlayer() . Puis, passez le joueur en tant que paramètre.


    humanoid.Died:Connect(function()
    respawnPlayerInLobby(player)
    removeActivePlayer(player)
    end)
  2. Pour voir si un joueur gagnant est trouvé, démarrez un serveur de test . Lorsqu'il ne reste qu'un seul joueur, vous devriez voir FoundWinner dans la fenêtre d'sortie.

  3. Continuez à tester et laissez le match s'arrêter. Remarquez qu'un nouveau match commence, une erreur apparaît dans la fenêtre de sortie :

Cette erreur est due au fait que le minuteur n'a pas été arrêté, qui sera réparé dans la prochaine section.

Arrêt du minuteur

Lorsque un match se termine avec un joueur gagnant, le minuteur doit s'arrêter également. Pour arrêter le minuteur avant la fin du temps, faites en sorte que le minuteur s'arrête chaque fois que l'événement de fin de match se déclenche. C'est l'un des avantages de la création d'événements. Ils peuvent être réutilisés dans plusieurs situations pour déclencher des relations de script d'effet.

  1. Dans MatchManager, créez une nouvelle fonction locale nommée stopTimer() . À l'intérieur, tapez myTimer:stop() pour arrêter le minuteur.


    -- Crée un nouvel objet de minuterie à utiliser pour suivre le temps du match.
    local myTimer = timer.new()
    -- Fonctions locales
    local function stopTimer()
    myTimer:stop()
    end
    local function timeUp()
    matchEnd:Fire(gameSettings.endStates.TimerUp)
    end
  2. Pour arrêter le minuteur lorsque le match se termine, connectez l'événement de fin de match à stopTimer() .


    -- Fonctions de module
    function MatchManager.prepareGame()
    playerManager.sendPlayersToMatch()
    matchStart:Fire()
    end
    matchStart.Event:Connect(startTimer)
    matchEnd.Event:Connect(stopTimer)
    return MatchManager
  3. Testez que l'erreur précédente n'apparaît plus en démarrant un serveur . Éliminez tous sauf un joueur et attendez quelques secondes une fois la partie terminée.

Prochains pas

Bien que les deux conditions de victoire soient terminées, il reste encore quelques tâches à terminer pour terminer la boucle de jeu. Par instance, le joueur gagnant n'est jamais téléporté dans le lobby. Dans la prochaine leçon, vous afficherez comment le match s'est terminé pour les joueurs et réinitialisez le jeu, ce qui finalise enfin la boucle.

Scripts terminés

Ceux-ci sont des scripts terminés pour vérifier vos travaux.

Script PlayerManager


local PlayerManager = {}
-- Services
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Modules
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
-- Événements
local events = ServerStorage:WaitForChild("Events")
local matchEnd = events:WaitForChild("MatchEnd")
-- Variables de carte
local lobbySpawn = workspace.Lobby.StartSpawn
local arenaMap = workspace.Arena
local spawnLocations = arenaMap.SpawnLocations
-- Valeurs
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local playersLeft = displayValues:WaitForChild("PlayersLeft")
-- Variables du joueur
local activePlayers = {}
local playerWeapon = ServerStorage.Weapon
-- Fonctions locales
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
-- Fonctions de module
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
-- Événements
Players.PlayerAdded:Connect(onPlayerJoin)
return PlayerManager

Script GameSettings


local GameSettings = {}
-- Variables de jeu
GameSettings.intermissionDuration = 5
GameSettings.matchDuration = 10
GameSettings.minimumPlayers = 2
GameSettings.transitionTime = 5
-- Possibles façons que le jeu puisse se terminer.
GameSettings.endStates = {
TimerUp = "TimerUp",
FoundWinner = "FoundWinner"
}
return GameSettings

Script de GameManager


-- Services
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
-- Scripts de module
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local matchManager = require(moduleScripts:WaitForChild("MatchManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
local displayManager = require(moduleScripts:WaitForChild("DisplayManager"))
-- Événements
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

Script de MatchManager


local MatchManager = {}
-- Services
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- Scripts de module
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local playerManager = require(moduleScripts:WaitForChild("PlayerManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
local timer = require(moduleScripts:WaitForChild("Timer"))
-- Événements
local events = ServerStorage:WaitForChild("Events")
local matchStart = events:WaitForChild("MatchStart")
local matchEnd = events:WaitForChild("MatchEnd")
-- Valeurs
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local timeLeft = displayValues:WaitForChild("TimeLeft")
-- Crée un nouvel objet de minuterie à utiliser pour suivre le temps du match.
local myTimer = timer.new()
-- Fonctions locales
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
-- Ajouter +1 fait en sorte que l'afficheur de temps s'affiche à 1 au lieu de 0.
timeLeft.Value = (math.floor(myTimer:getTimeLeft() + 1))
-- En ne définissant pas le temps d'attente, il offre un meilleur suivi
task.wait()
end
end
-- Fonctions de module
function MatchManager.prepareGame()
playerManager.sendPlayersToMatch()
matchStart:Fire()
end
matchStart.Event:Connect(startTimer)
matchEnd.Event:Connect(stopTimer)
return MatchManager