クリーンアップとリセット

*このコンテンツは、ベータ版のAI(人工知能)を使用して翻訳されており、エラーが含まれている可能性があります。このページを英語で表示するには、 こちら をクリックしてください。

ゲームの最後のフェーズをコード化する時間:クリーンアップとリセット。このフェーズのコードは、ゲームループが中断され、将来のマッチが各プレイヤーにとって同じように開始することを保証します。

GUI を更新

クリーンアップとリセットを行う前に、ディスプレイマネージャーを使用してゲームがどのように終了したかをプレイヤーに通知し、適切な状態を表示します。

勝者の名前を取得する

勝利したプレイヤーの名前を取得して始めることで、もしそれがあった場合。以前、コードはアクティブなプレイヤーテーブルのサイズが 1 に落ちたかどうかをチェックしました。残りのプレイヤーの名前を取得するには、そのテーブルの最初のインデックスで名前を返します。

  1. PlayerManager で、新しいモジュール機能 getWinnerName() と名付けられた新しい機能を開始します。


    function PlayerManager.getWinnerName()
    end
    -- イベント
    Players.PlayerAdded:Connect(onPlayerJoin)
  2. if 文を追加して、activePlayers[1] に何かが存在する場合に実行されます。テーブルカウントは以前チェックされていましたが、プレイヤーは切断されたか、ゲームを終了した可能性があります。


    function PlayerManager.getWinnerName()
    local winningPlayer = activePlayers[1]
    if winningPlayer then
    end
    end
  3. if 文で:

    • プレイヤーの名前を返す。
    • その他は、エラーストリングを返します。

    function PlayerManager.getWinnerName()
    local winningPlayer = activePlayers[1]
    if winningPlayer then
    return winningPlayer.Name
    else
    return "Error: No winning player found"
    end
    end

最終状態を取得する

モジュール機能を使用して、タイマーが終了するか、1人のプレイヤーが残されるかにかかわらず、正しい終了状態から情報を取得します。次に、その状態変数を DisplayManager に送信して、適切なメッセージでステータス GUIを更新します。

  1. In マッチマネージャー , パラメーター名 getEndStatus() という新しいモジュール機能をコード化し、名前 endState のパラメーターを持つ。送信されるメッセージを保存するには、空の変数 statusToReturn を追加します。


    function MatchManager.prepareGame()
    playerManager.sendPlayersToMatch()
    matchStart:Fire()
    end
    function MatchManager.getEndStatus(endState)
    local statusToReturn
    end
    matchStart.Event:Connect(startTimer)
    matchEnd.Event:Connect(stopTimer)
    return MatchManager
  2. if および elseif 文を使用して statusToReturn の値を設定します。最終状態変数: FoundWinnerTimerUp をチェックします。エラーチェックのため、最後に別のものを含めます。


    function MatchManager.getEndStatus(endState)
    local statusToReturn
    if endState == gameSettings.endStates.FoundWinner then
    elseif endState == gameSettings.endStates.TimerUp then
    else
    end
    end
  3. 各条件に次のものを追加します:

    FoundWinner

    • playerManager.getWinnerName() を使用した勝者の変数。
    • 更新 statusToReturn 勝者を発表するストリングで更新。

    TimerUp

    • 更新 statusToReturn 時間切れを発表するストリングで更新。

    Else

    • 終了ゲームメッセージを取得する際に問題が発生した場合、エラーメッセージで statusToReturn を更新

    function MatchManager.getEndStatus(endState)
    local statusToReturn
    if endState == gameSettings.endStates.FoundWinner then
    local winnerName = playerManager.getWinnerName()
    statusToReturn = "Winner is : " .. winnerName
    elseif endState == gameSettings.endStates.TimerUp then
    statusToReturn = "Time ran out!"
    else
    statusToReturn = "Error found"
    end
    end
  4. return statusToReturn をタイプしてメッセージを戻します。


    function MatchManager.getEndStatus(endState)
    local statusToReturn
    if endState == gameSettings.endStates.FoundWinner then
    local winnerName = playerManager.getWinnerName()
    statusToReturn = "Winner is : " .. winnerName
    elseif endState == gameSettings.endStates.TimerUp then
    statusToReturn = "Time ran out!"
    else
    statusToReturn = "Error found"
    end
    return statusToReturn
    end

表示とテスト

ゲームマネージャーで更新されたアナウンスを取得し、ディスプレイマネージャーを使用してプレイヤーに表示します。

  1. Open ゲームマネージャー 。while 真のループでは、 最後の印刷文を削除 します。次に、endStatus という名前の変数を作成します。それを matchManager.getEndStatus(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()
    local endStatus = matchManager.getEndStatus(endState)
    end
  2. 返されたメッセージを GUI ラベルに表示するには、displayManager.updateStatus() を呼び出し、endStatus をパスします。


    local endStatus = matchManager.getEndStatus(endState)
    displayManager.updateStatus(endStatus)
  3. それで、ゲームは一時停止して、プレイヤーがメッセージを見るようにし、transitionTime を使って待機を追加します。


    local endStatus = matchManager.getEndStatus(endState)
    displayManager.updateStatus(endStatus)
    task.wait(gameSettings.transitionTime)
  4. テストサーバー を開始し、プレイヤーが時間切れと勝利したプレイヤーの条件に次のメッセージを見るかどうかをチェックします。

    時間切れ条件
    勝つプレイヤーの条件

トラブルシュートのヒント

この時点では、メッセージを見ることができません。以下のいずれかを試してください。

  • エンドステータスメッセージが「エラーが見つかりました」の場合、条件のいずれも成功しませんでした。コードを MatchManager.getEndStatus() コードサンプルと対比してチェックします。
  • 終了状態が表示されない場合は、メッセージを displayManager に送信した後に task.wait(gameSettings.transitionTime) が表示されているかどうかを確認してください。

新しいマッチを開始

新しいマッチを開始する前に、短い移行があります。これにより、プレイヤーには終了状態を見る時間が与えられ、ロビーへのテレポートがより驚きに満ちたものになります。

移行の終わりに、残りのプレイヤーはアリーナから削除され、すべてのコードがリセットされます。これにより、プレイヤーが次の試合をクリーンなゲームバージョンで開始できるようになります。

移行を処理する

プレイヤーが移行状態に移動すると、武器を削除します。

  1. PlayerManager で、ローカル機能を見つけます。下のハイライトされたコードをコピーして貼り付けます removePlayerWeapon()。コードは、アクティブに装備されているか、プレイヤーのバックパックに入っている個々の武器を削除します。


    local function removePlayerWeapon(whichPlayer)
    -- プレイヤーが切断されたり、退出した場合に存在するかどうかをチェックします。
    if whichPlayer then
    local character = whichPlayer.Character
    -- プレイヤーが現在、そのキャラクターに持っている場合
    local weapon = character:FindFirstChild("Weapon")
    if weapon then
    weapon:Destroy()
    end
    -- プレイヤーがバックパックに武器を持っている場合
    local backpackWeapon = whichPlayer.Backpack:FindFirstChild("Weapon")
    if backpackWeapon then
    backpackWeapon:Destroy()
    end
    else
    print("No player to remove weapon")
    end
    end
  2. 新しいモジュール機能 removeAllWeapons() と名付けられた新しい機能を開始します。


    function PlayerManager.removeAllWeapons()
    end
    -- イベント
    Players.PlayerAdded:Connect(onPlayerJoin)
    return PlayerManager
  3. その機能では、for ループを使用してアクティブなプレイヤーテーブルを通り抜けます。ループでは、removePlayerWeapon() を呼び出し、見つかったプレイヤーをパスします。


    function PlayerManager.removeAllWeapons()
    for playerKey, whichPlayer in activePlayers do
    removePlayerWeapon(whichPlayer)
    end
    end

マッチの間のクリーンアップ

クリーンアップは、MatchManager の独自の機能になります。今のところ、クリーンアップは以前に作成された関数を使用してプレイヤーの武器を削除します。ゲームを拡大すると、マップをリセットする機能など、より多くのものが追加できます。たとえば、試合中に変更されたマップをリセットする機能などです。

  1. Open MatchManager。新しいモジュール機能名 cleanupMatch() を追加します。その機能で、playerManager.removeAllWeapons() を呼び出します。


    function MatchManager.cleanupMatch()
    playerManager.removeAllWeapons()
    end
    matchStart.Event:Connect(startTimer)
    matchEnd.Event:Connect(stopTimer)
    return MatchManager
  2. 次に、クリーンアップ関数を呼び出します。Open ゲームマネージャー と while true do ループを見つけるそのため、プレイヤーは終了インターミッション中に武器を削除し、最後の matchManager.cleanupMatch() の前に task.wait() を呼び出します。


    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()
    local endStatus = matchManager.getEndStatus(endState)
    displayManager.updateStatus(endStatus)
    matchManager.cleanupMatch()
    task.wait(gameSettings.transitionTime)
    end
  3. テストサーバーを開始し、マッチを実行します。タイマーが切れるのを待って、終了ゲーム休憩中にプレイヤーの武器が削除されることを確認します。

    試合中
    試合後

一致をリセット

ゲーム内でいくつかの他のことに気付いたかもしれません、例えば、試合が終了した後もプレイヤーがアリーナに残っているなど。一致がクリーンアップされたので、次にゲームをリセットします。これには、アリーナのプレイヤーをロビーに戻し、アクティブなプレイヤーのテーブルをクリアすることが含まれます。リセットが行われると、ゲームループは無期限に実行できます。

まず、プレイヤーをロビーに戻す機能を開始します。

  1. PlayerManager で:

    • モジュール機能名 resetPlayers() を作成します。
    • アクティブなプレイヤーを順回しする for ループを追加します。
    • ループで respawnPlayerInLobby() を呼び出し、プレイヤーをパラメータとして渡します。

    function PlayerManager.resetPlayers()
    for playerKey, whichPlayer in activePlayers do
    respawnPlayerInLobby(whichPlayer)
    end
    end
    -- イベント
    Players.PlayerAdded:Connect(onPlayerJoin)
    return PlayerManager
  2. 次のマッチに備えて、activePlayers テーブルを空に設定して、空のテーブルにリセットする簡単な方法である {} と同じに設定してください。


    function PlayerManager.resetPlayers()
    for playerKey, whichPlayer in activePlayers do
    respawnPlayerInLobby(whichPlayer)
    end
    activePlayers = {}
    end
  3. Open MatchManager。新しいモジュール関数名 resetMatch() をコードし、playerManager.resetPlayers() を呼び出します。


    function MatchManager.resetMatch()
    playerManager.resetPlayers()
    end
    matchStart.Event:Connect(startTimer)
    matchEnd.Event:Connect(stopTimer)
    return MatchManager
  4. 戻る ゲームマネージャー 。while true ループの終わりに、matchManager.resetMatch() を呼び出す。


    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()
    local endStatus = matchManager.getEndStatus(endState)
    displayManager.updateStatus(endStatus)
    matchManager.cleanupMatch()
    task.wait(gameSettings.transitionTime)
    matchManager.resetMatch()
    end
  5. テストサーバーを開始し、マッチを実行します。少なくともエラーなしで 2 ゲームループを通過できることを確認します。

完了したスクリプト

以下は、作業を確認するための完了したスクリプトです。

ゲームマネージャースクリプト


-- サービス
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
-- モジュールスクリプト
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local matchManager = require(moduleScripts:WaitForChild("MatchManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
local displayManager = require(moduleScripts:WaitForChild("DisplayManager"))
-- イベント
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()
local endStatus = matchManager.getEndStatus(endState)
displayManager.updateStatus(endStatus)
matchManager.cleanupMatch()
task.wait(gameSettings.transitionTime)
matchManager.resetMatch()
end

MatchManager スクリプト


local MatchManager = {}
-- サービス
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- モジュールスクリプト
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local playerManager = require(moduleScripts:WaitForChild("PlayerManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
local displayManager = require(moduleScripts:WaitForChild("DisplayManager"))
local timer = require(moduleScripts:WaitForChild("Timer"))
-- イベント
local events = ServerStorage:WaitForChild("Events")
local matchStart = events:WaitForChild("MatchStart")
local matchEnd = events:WaitForChild("MatchEnd")
-- 値
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local timeLeft = displayValues:WaitForChild("TimeLeft")
-- マッチ時間を追跡するために使用される新しいタイマーオブジェクトを作成します。
local myTimer = timer.new()
-- ローカル機能
local function stopTimer()
myTimer:stop()
end
local function timeUp()
matchEnd:Fire(gameSettings.endStates.TimerUp)
end
local function startTimer()
myTimer:start(gameSettings.matchDuration)
myTimer.finished:Connect(timeUp)
while myTimer:isRunning() do
-- +1 を追加すると、タイマーの表示が 0 ではなく 1 で終わることを保証できます。
timeLeft.Value = (myTimer:getTimeLeft() + 1) // 1
-- 待機時間を設定しないことで、より正確なループが提供されます
task.wait()
end
end
-- モジュール機能
function MatchManager.prepareGame()
playerManager.sendPlayersToMatch()
matchStart:Fire()
end
function MatchManager.getEndStatus(endState)
local messageToReturn
if endState == gameSettings.endStates.FoundWinner then
local winnerName = playerManager.getWinnerName()
messageToReturn = "Winner is : " .. winnerName
elseif endState == gameSettings.endStates.TimerUp then
messageToReturn = "Time ran out!"
else
messageToReturn = "Error found"
end
return messageToReturn
end
function MatchManager.cleanupMatch()
playerManager.removeAllWeapons()
end
function MatchManager.resetMatch()
playerManager.resetPlayers()
end
matchStart.Event:Connect(startTimer)
matchEnd.Event:Connect(stopTimer)
return MatchManager

PlayerManager スクリプト


local PlayerManager = {}
-- サービス
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- モジュール
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
-- イベント
local events = ServerStorage:WaitForChild("Events")
local matchEnd = events:WaitForChild("MatchEnd")
-- マップ変数
local lobbySpawn = workspace.Lobby.StartSpawn
local arenaMap = workspace.Arena
local spawnLocations = arenaMap.SpawnLocations
-- 値
local displayValues = ReplicatedStorage:WaitForChild("DisplayValues")
local playersLeft = displayValues:WaitForChild("PlayersLeft")
-- プレイヤー変数
local activePlayers = {}
local playerWeapon = ServerStorage.Weapon
local function checkPlayerCount()
if #activePlayers == 1 then
matchEnd:Fire(gameSettings.endStates.FoundWinner)
print("Found winner")
end
end
local function removeActivePlayer(player)
print("removing 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 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
local function onPlayerJoin(player)
player.RespawnLocation = lobbySpawn
end
local function removePlayerWeapon(whichPlayer)
-- プレイヤーが切断されたり、退出した場合に存在するかどうかをチェックします。
if whichPlayer then
local character = whichPlayer.Character
-- プレイヤーが現在、そのキャラクターに持っている場合
local weapon = character:FindFirstChild("Weapon")
if weapon then
weapon:Destroy()
end
-- プレイヤーがバックパックに武器を持っている場合
local backpackWeapon = whichPlayer.Backpack:FindFirstChild("Weapon")
if backpackWeapon then
backpackWeapon:Destroy()
end
else
print("No player to remove weapon")
end
end
function PlayerManager.sendPlayersToMatch()
local availableSpawnPoints = spawnLocations:GetChildren()
for playerKey, whichPlayer in Players:GetPlayers() do
table.insert(activePlayers,whichPlayer)
-- スポーン場所を取得し、次のプレイヤーが次のスポーンを得るようにテーブルから削除する
local spawnLocation = table.remove(availableSpawnPoints, 1)
preparePlayer(whichPlayer, spawnLocation)
end
playersLeft.Value = #activePlayers
end
function PlayerManager.getWinnerName()
local winningPlayer = activePlayers[1]
if winningPlayer then
return winningPlayer.Name
else
return "Error: No player found"
end
end
function PlayerManager.removeAllWeapons()
for playerKey, whichPlayer in activePlayers do
removePlayerWeapon(whichPlayer)
end
end
function PlayerManager.resetPlayers()
for playerKey, whichPlayer in activePlayers do
respawnPlayerInLobby(whichPlayer)
end
activePlayers = {}
end
-- イベント
Players.PlayerAdded:Connect(onPlayerJoin)
return PlayerManager