マップを作成したら次はプログラムです。このコースの残りの部分では、ゲームループの様々な要素をスクリプト化することに重点を置いています。
スクリプトの設定
バトルロイヤルは、モジュールスクリプトと通常のスクリプトを組み合わせて使用します。以下、スクリプトとその機能です。
GameManager | 通常のスクリプトです。GameSettingsの変数を使用して、MatchManagerの関数を実行します。ゲームのメインループはここになります。 |
MatchManager | モジュール スクリプトです。プレーヤーをアリーナに送り込んだり、試合の時間を追跡したりするなどの機能を実行します。 |
GameSettings | モジュール スクリプトです。他のスクリプトで使用される共通変数を格納します。 |
GameSettingsスクリプト
GameSettings という名前のモジュール スクリプトを作成して、試合や休憩時間など、他のスクリプトで使用される変数を保存します。これらの変数は、後で GameManager スクリプトによって使用されます。
- ServerStorageで、ModuleScripts という名前のフォルダーを作成します。そのフォルダーで、GameSettings という名前の新しいモジュールスクリプトを作成します。
- GameSettings を開き、スクリプトの名前と一致するようにモジュールテーブルの名前を変更します。
local GameSettings = {}
return GameSettings
- モジュールテーブルで、次の使用のための変数を追加します。各値について最善の推測を行います。後でテストするときにいつでも変更できます。
- intermissionDuration: プレイヤーが試合前に待機する秒数
- matchDuration:試合時間
- minimumPlayers:試合開始に必要な最小プレーヤー数
- transitionTime:試合前後の時間 (ゲームループの部分間の移行をより唐突にしないようにする)
local GameSettings = {}
-- Game Variables
GameSettings.intermissionDuration = 5
GameSettings.matchDuration = 10
GameSettings.minimumPlayers = 2
GameSettings.transitionTime = 5
return GameSettings
MatchManger スクリプト
GameManager に接続されている2つ目のスクリプトは、MatchManagerです。このスクリプトは、タイマーの開始や試合終了後のプレイヤーのリセットなどのタスクを管理します。
MatchManager 内には、 prepareGame() という名前の関数があり、プレーヤーを試合に移行してゲームを開始します。
- ServerStorage の ModuleScripts というフォルダに、 MatchManager という名前のモジュールスクリプトを追加します。モジュールテーブルの名前を下記の通りに変更します。
local MatchManager = {}
return MatchManager
- prepareGame() という名前の新しいモジュール関数を MatchManager に追加します。後でスクリプトをテストするために print 文を入れておきます。
local MatchManager = {}
function MatchManager.prepareGame()
print("Game starting!")
end
return MatchManager
ゲームループのコーディング
ゲームループは、GameManager スクリプトの中で、先ほど作成した変数を使ってコーディングされます。ゲームループには、休憩、競技、後片付けとリセットの3つの段階があることを忘れないでください。
GameManager スクリプト
このスクリプトは通常のサーバースクリプトなので、ModuleScripts フォルダではなく、ServerScriptService にそのまま配置します。実際のゲーム ループは while true do ループになります。
- ServerScriptService で、GameManager という名前の新しいスクリプトを作成します。
- Modulescripts があるサービス「ServerStorage」の変数を追加します。次に、サービス「Players」の変数を追加します。これは、休憩中にプレイヤー数を確認するために必要です。
-- Services
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
- 以前に作成したモジュールを使用する場合
- moduleScripts という名前の変数を ModuleScripts フォルダの場所に設定します。
- matchManager および gameSettings という名前の変数を追加します。それぞれの変数に、require を使ってモジュールを読み込みます。
-- Services
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
-- Module Scripts
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local matchManager = require(moduleScripts:WaitForChild("MatchManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
- 変数の後に、while true doループを追加します。ゲームループのすべてのフェーズは、この中に入って無限に繰り返されます。
- Module Scripts
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local matchManager = require(moduleScripts:WaitForChild("MatchManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
-- Main game loop
while true do
end
インターミッションのコーディング
ゲームのループは無限に続きますが、インターミッションはループを一時停止し、試合が開始できるプレイヤー数に達した場合にのみ続行する必要があります。この一時停止をコード化するには、while ループの中にインターミッションのためのネストされた繰り返しループを含めます。このネストされたループは、十分な数のプレーヤーが集まるまで繰り返し、メインループを一時停止します。十分な数のプレーヤーが集まると、ループは終了し、プレーヤーは試合に移行します。
repeat ループでは、ループ内のコードは少なくとも1回は実行されます。while ループとは異なり、ループが終了するまで条件をチェックしません。これにより、プレイヤーは試合前に必ずロビーに行くようになります。
- while true do ループの中で、repeat と入力して Enter を押すと、自動的に until というキーワードが出ます。
while true do
repeat
until
end
- 現在のプレイヤー数(Players.NumPlayers)が、GameSettings モジュールで先に作成した minimumPlayers 変数以上かどうかをチェックします。
while true do
repeat
until Players.NumPlayers >= gameSettings.minimumPlayers
end
- 繰り返しループの中で、インターミッションが始まるという print 文を追加します。GameSettings のintermissionDuration を使って、その秒数だけ wait() で一時停止します。
while true do
repeat
print("Starting intermission")
wait(gameSettings.intermissionDuration)
until Players.NumPlayers >= gameSettings.minimumPlayers
end
- プレイテストを行い、print 文「Starting intermission」が少なくとも2回表示されることを確認します。メッセージが2回表示されるのは、リピートループが十分なプレイヤーを見つけられず、再度実行されたことを証明しています。2回目のメッセージを見るには、インターミッションの長さを待つ必要があります。
トラブルシューティング
この時点で、意図したとおりにスポーンしない場合は、次のいずれかを試してください。
- wait() は repeat ループの中に入れてください。wait がないと、スクリプトは1秒間に何度も実行され、Roblox Studio に負荷をかけ、エラーを発生させます。
- Game Settings モジュールの変数 intermissionDuration は、1より大きくする必要があります。これより小さいと、スクリプトが頻繁に繰り返され、スローダウンの問題が発生することがあります。
インターミッションの終了
試合ができる人数が揃ったら、短い遷移時間だけ待機させます。その後に MatchManager の prepareGame() 関数を呼び出して、プレイヤー達を試合に送り込みます。この関数は一行を表示するだけですが、後でもっとコードを追加することを忘れないでください。
- repeat ループの最後に、「Intermission over」という print 文を追加して、コードをテストしてください。そして、GameSettingのtransitionTime変数を使ってwait() を実行します。
while true do
repeat
print("Starting intermission")
wait(gameSettings.intermissionDuration)
until Players.NumPlayers >= gameSettings.minimumPlayers
print("Intermission over")
wait(gameSettings.transitionTime )
end
コードは while ループの範囲内(do と end の間)に収めてください。ループの外にコードがあると、ゲームループの一部が繰り返されず、プレイヤーはインターミッションのフェーズで立ち往生するだけになるかもしれません。
- 待機後、MatchManager モジュールから prepareGame() を呼び出します。このコードが実行されると、出力ウィンドウにテキストが印刷されるだけです。このコードをテストするには、次のセクションまでお待ちください。
while true do
repeat
print("Starting intermission")
wait(gameSettings.intermissionDuration)
until Players.NumPlayers >= gameSettings.minimumPlayers
print("Intermission over")
wait(gameSettings.transitionTime)
matchManager.prepareGame()
end
このプロジェクトの後にスクリプトを追加する場合、while true do ループ以下のコードは実行されないことに留意してください。関連するコードは while ループの中に入れるか、メインループからモジュール関数を呼び出してください。
マルチプレイヤー ゲームのテスト
現在、prepareGame() を実行させるためには、repeat ループを抜ける必要があります。しかし、そのためには、プレイヤーが2人以上必要です。つまり、Playボタンを使用しても、ゲーム内のプレイヤーは自分1人だけなので、repeat ループから抜けられず、関数は実行されません(最小プレイヤー数が1人でない限り)。これをテストするには、マルチプレイヤーゲームをシミュレートする必要があります。
ローカル サーバーの起動
複数のプレイヤーを必要とするコードをテストするには、ローカルサーバーを作成します。公開されているゲームは通常Robloxサーバー上にありますが、ローカルサーバーはあなたのコンピュータ上で模擬プレイヤーによるマルチプレイヤーゲームをシミュレートするものです。
- ローカルサーバを起動するには、「TEST/テスト」タブの「Clients and Servers/クライアントとサーバー」セクションの GameSetting の変数 minimumPlayers にあるプレイヤーの数を設定します。このレッスンでは、「2 Players/2人のプレイヤー」を使用します。
- 「Start/開始」をクリックしてサーバーを開始します。
- サーバーがセットアップされるまで数秒待ちます。元のStudioウィンドウに加え、複数のウィンドウが開きます。ファイアウォールやその他のオンラインセキュリティソフトウェアから Roblox Studio へのアクセスを許可する必要があるかもしれません。
トラブルシューティング
この時点で、テストサーバーを見ることができない場合は、以下のいずれかをお試しください。
- サーバーの起動に問題がある場合は、「ファイアウォールとルーターの問題」の記事を再確認してください。
- プレーヤーの数を 2 人または 3 人などの少人数に設定します。
- 問題が解決しない場合は、Roblox Studio を再起動するか、コンピューターを再起動してみてください。
ローカル サーバーでのテスト
サーバーが起動すると、複数のウィンドウが表示されます。それぞれが、サーバーとクライアントの関係の異なる部分を表しています。
- 緑色の枠:サーバーの状態を表します。
- 青色の枠:各プレーヤー(クライアント)の様子をシミュレートしています。
サーバーを立ち上げた状態で、コードがうまくいったかどうかを確認することができます。
- 緑色の枠で囲まれた「Server/サーバー」ウィンドウを探します。MatchManager スクリプトから呼び出されたprint 文を確認します。リピートループがあるため、同じprint文が繰り返されているのがわかります。
- 「Cleanup/クリーンアップ」ボタンをクリックするとウィンドウが閉じテストが終了できます。
トラブルシューティング
この時点で、意図した print 文が表示されない場合は、次のいずれかを試してください。
- prepareGame() などの関数が while true do ループのスコープ内にあることを確認します。
- MatchManager からの print がうまくいかなかった場合は、GameManager で MatchManager スクリプトがrequired で呼び出しているか、そのモジュールのテーブルに prepareGame() が追加されているかなど、モジュールスクリプトでよくあるトラブルシューティングを確認してみてください。
完成したスクリプト
以下に、完成したスクリプトを掲載しますのでチェックしてみてください。
GameManager スクリプト
-- Services
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
-- Module Scripts
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local matchManager = require(moduleScripts:WaitForChild("MatchManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
-- Main game loop
while true do
repeat
print("Starting intermission")
wait(gameSettings.intermissionDuration)
until Players.NumPlayers >= gameSettings.minimumPlayers
print("Intermission over")
wait(gameSettings.transitionTime)
matchManager.prepareGame()
end
MatchManager スクリプト
local MatchManager = {}
function MatchManager.prepareGame()
print("Game starting!")
end
return MatchManager
GameSettings スクリプト
local GameSettings = {}
-- Game Variables
GameSettings.intermissionDuration = 5
GameSettings.roundDuration = 10
GameSettings.minimumPlayers = 2
GameSettings.transitionTime = 5
return GameSettings
[ 1.プロジェクトのセットアップ ]
[ 3.プレイヤーの管理 ]