ゲームの最後のフェーズをコード化する時間:クリーンアップとリセット。このフェーズのコードは、ゲームループが中断され、将来のマッチが各プレイヤーにとって同じように開始することを保証します。
GUI を更新
クリーンアップとリセットを行う前に、ディスプレイマネージャーを使用してゲームがどのように終了したかをプレイヤーに通知し、適切な状態を表示します。
勝者の名前を取得する
勝利したプレイヤーの名前を取得して始めることで、もしそれがあった場合。以前、コードはアクティブなプレイヤーテーブルのサイズが 1 に落ちたかどうかをチェックしました。残りのプレイヤーの名前を取得するには、そのテーブルの最初のインデックスで名前を返します。
PlayerManager で、新しいモジュール機能 getWinnerName() と名付けられた新しい機能を開始します。
function PlayerManager.getWinnerName()end-- イベントPlayers.PlayerAdded:Connect(onPlayerJoin)if 文を追加して、activePlayers[1] に何かが存在する場合に実行されます。テーブルカウントは以前チェックされていましたが、プレイヤーは切断されたか、ゲームを終了した可能性があります。
function PlayerManager.getWinnerName()local winningPlayer = activePlayers[1]if winningPlayer thenendendif 文で:
- プレイヤーの名前を返す。
- その他は、エラーストリングを返します。
function PlayerManager.getWinnerName()local winningPlayer = activePlayers[1]if winningPlayer thenreturn winningPlayer.Nameelsereturn "Error: No winning player found"endend
最終状態を取得する
モジュール機能を使用して、タイマーが終了するか、1人のプレイヤーが残されるかにかかわらず、正しい終了状態から情報を取得します。次に、その状態変数を DisplayManager に送信して、適切なメッセージでステータス GUIを更新します。
In マッチマネージャー , パラメーター名 getEndStatus() という新しいモジュール機能をコード化し、名前 endState のパラメーターを持つ。送信されるメッセージを保存するには、空の変数 statusToReturn を追加します。
function MatchManager.prepareGame()playerManager.sendPlayersToMatch()matchStart:Fire()endfunction MatchManager.getEndStatus(endState)local statusToReturnendmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManagerif および elseif 文を使用して statusToReturn の値を設定します。最終状態変数: FoundWinner と TimerUp をチェックします。エラーチェックのため、最後に別のものを含めます。
function MatchManager.getEndStatus(endState)local statusToReturnif endState == gameSettings.endStates.FoundWinner thenelseif endState == gameSettings.endStates.TimerUp thenelseendend各条件に次のものを追加します:
FoundWinner
- playerManager.getWinnerName() を使用した勝者の変数。
- 更新 statusToReturn 勝者を発表するストリングで更新。
TimerUp
- 更新 statusToReturn 時間切れを発表するストリングで更新。
Else
- 終了ゲームメッセージを取得する際に問題が発生した場合、エラーメッセージで statusToReturn を更新
function MatchManager.getEndStatus(endState)local statusToReturnif endState == gameSettings.endStates.FoundWinner thenlocal winnerName = playerManager.getWinnerName()statusToReturn = "Winner is : " .. winnerNameelseif endState == gameSettings.endStates.TimerUp thenstatusToReturn = "Time ran out!"elsestatusToReturn = "Error found"endendreturn statusToReturn をタイプしてメッセージを戻します。
function MatchManager.getEndStatus(endState)local statusToReturnif endState == gameSettings.endStates.FoundWinner thenlocal winnerName = playerManager.getWinnerName()statusToReturn = "Winner is : " .. winnerNameelseif endState == gameSettings.endStates.TimerUp thenstatusToReturn = "Time ran out!"elsestatusToReturn = "Error found"endreturn statusToReturnend
表示とテスト
ゲームマネージャーで更新されたアナウンスを取得し、ディスプレイマネージャーを使用してプレイヤーに表示します。
Open ゲームマネージャー 。while 真のループでは、 最後の印刷文を削除 します。次に、endStatus という名前の変数を作成します。それを matchManager.getEndStatus(endState) を呼び出すと同じに設定します。
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()local endStatus = matchManager.getEndStatus(endState)end返されたメッセージを GUI ラベルに表示するには、displayManager.updateStatus() を呼び出し、endStatus をパスします。
local endStatus = matchManager.getEndStatus(endState)displayManager.updateStatus(endStatus)それで、ゲームは一時停止して、プレイヤーがメッセージを見るようにし、transitionTime を使って待機を追加します。
local endStatus = matchManager.getEndStatus(endState)displayManager.updateStatus(endStatus)task.wait(gameSettings.transitionTime)テストサーバー を開始し、プレイヤーが時間切れと勝利したプレイヤーの条件に次のメッセージを見るかどうかをチェックします。
時間切れ条件 勝つプレイヤーの条件
トラブルシュートのヒント
この時点では、メッセージを見ることができません。以下のいずれかを試してください。
- エンドステータスメッセージが「エラーが見つかりました」の場合、条件のいずれも成功しませんでした。コードを MatchManager.getEndStatus() コードサンプルと対比してチェックします。
- 終了状態が表示されない場合は、メッセージを displayManager に送信した後に task.wait(gameSettings.transitionTime) が表示されているかどうかを確認してください。
新しいマッチを開始
新しいマッチを開始する前に、短い移行があります。これにより、プレイヤーには終了状態を見る時間が与えられ、ロビーへのテレポートがより驚きに満ちたものになります。
移行の終わりに、残りのプレイヤーはアリーナから削除され、すべてのコードがリセットされます。これにより、プレイヤーが次の試合をクリーンなゲームバージョンで開始できるようになります。
移行を処理する
プレイヤーが移行状態に移動すると、武器を削除します。
PlayerManager で、ローカル機能を見つけます。下のハイライトされたコードをコピーして貼り付けます removePlayerWeapon()。コードは、アクティブに装備されているか、プレイヤーのバックパックに入っている個々の武器を削除します。
local function removePlayerWeapon(whichPlayer)-- プレイヤーが切断されたり、退出した場合に存在するかどうかをチェックします。if whichPlayer thenlocal character = whichPlayer.Character-- プレイヤーが現在、そのキャラクターに持っている場合local weapon = character:FindFirstChild("Weapon")if weapon thenweapon:Destroy()end-- プレイヤーがバックパックに武器を持っている場合local backpackWeapon = whichPlayer.Backpack:FindFirstChild("Weapon")if backpackWeapon thenbackpackWeapon:Destroy()endelseprint("No player to remove weapon")endend新しいモジュール機能 removeAllWeapons() と名付けられた新しい機能を開始します。
function PlayerManager.removeAllWeapons()end-- イベントPlayers.PlayerAdded:Connect(onPlayerJoin)return PlayerManagerその機能では、for ループを使用してアクティブなプレイヤーテーブルを通り抜けます。ループでは、removePlayerWeapon() を呼び出し、見つかったプレイヤーをパスします。
function PlayerManager.removeAllWeapons()for playerKey, whichPlayer in activePlayers doremovePlayerWeapon(whichPlayer)endend
マッチの間のクリーンアップ
クリーンアップは、MatchManager の独自の機能になります。今のところ、クリーンアップは以前に作成された関数を使用してプレイヤーの武器を削除します。ゲームを拡大すると、マップをリセットする機能など、より多くのものが追加できます。たとえば、試合中に変更されたマップをリセットする機能などです。
Open MatchManager。新しいモジュール機能名 cleanupMatch() を追加します。その機能で、playerManager.removeAllWeapons() を呼び出します。
function MatchManager.cleanupMatch()playerManager.removeAllWeapons()endmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManager次に、クリーンアップ関数を呼び出します。Open ゲームマネージャー と while true do ループを見つけるそのため、プレイヤーは終了インターミッション中に武器を削除し、最後の matchManager.cleanupMatch() の前に task.wait() を呼び出します。
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()local endStatus = matchManager.getEndStatus(endState)displayManager.updateStatus(endStatus)matchManager.cleanupMatch()task.wait(gameSettings.transitionTime)endテストサーバーを開始し、マッチを実行します。タイマーが切れるのを待って、終了ゲーム休憩中にプレイヤーの武器が削除されることを確認します。
試合中 試合後
一致をリセット
ゲーム内でいくつかの他のことに気付いたかもしれません、例えば、試合が終了した後もプレイヤーがアリーナに残っているなど。一致がクリーンアップされたので、次にゲームをリセットします。これには、アリーナのプレイヤーをロビーに戻し、アクティブなプレイヤーのテーブルをクリアすることが含まれます。リセットが行われると、ゲームループは無期限に実行できます。
まず、プレイヤーをロビーに戻す機能を開始します。
PlayerManager で:
- モジュール機能名 resetPlayers() を作成します。
- アクティブなプレイヤーを順回しする for ループを追加します。
- ループで respawnPlayerInLobby() を呼び出し、プレイヤーをパラメータとして渡します。
function PlayerManager.resetPlayers()for playerKey, whichPlayer in activePlayers dorespawnPlayerInLobby(whichPlayer)endend-- イベントPlayers.PlayerAdded:Connect(onPlayerJoin)return PlayerManager次のマッチに備えて、activePlayers テーブルを空に設定して、空のテーブルにリセットする簡単な方法である {} と同じに設定してください。
function PlayerManager.resetPlayers()for playerKey, whichPlayer in activePlayers dorespawnPlayerInLobby(whichPlayer)endactivePlayers = {}endOpen MatchManager。新しいモジュール関数名 resetMatch() をコードし、playerManager.resetPlayers() を呼び出します。
function MatchManager.resetMatch()playerManager.resetPlayers()endmatchStart.Event:Connect(startTimer)matchEnd.Event:Connect(stopTimer)return MatchManager戻る ゲームマネージャー 。while true ループの終わりに、matchManager.resetMatch() を呼び出す。
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()local endStatus = matchManager.getEndStatus(endState)displayManager.updateStatus(endStatus)matchManager.cleanupMatch()task.wait(gameSettings.transitionTime)matchManager.resetMatch()endテストサーバーを開始し、マッチを実行します。少なくともエラーなしで 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 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()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