
[ROBLOX]ゲーム開発⑤(ステージクリア)
前回はRobloxのスクリプトを組む前に、前提となる知識を掘り下げた
今回はステージクリアの処理をいれてみる
クリア時の挙動
一般的なゲームはクリアすると何かしかのクリア演出があってタイトル画面やステージ選択画面に戻るのがスタンダードな流れだと思う
Robloxはオンラインゲームなので、ワールドにログインするとまずロビーに通され、そこで色々セッティングをしてから対戦相手とのマッチングをしてゲームステージに入る。で、ゲームが終了したらまたロビーに戻されるというパターンがスタンダードな感じがする

今回はあまり凝ったことはせずにゴールするとクリア演出が表示され、スタート地点に戻るように作ってみる
ゴールに触れたかどうかを検出する
エクスプローラー上でServerScrptServiceの中にScriptを追加する

追加されたScriptは "GoalService" とリネームしておく
Goalノード自体にはコリジョンがないので、そのパーツの土台に触れたかどうかを検出するようにする
しかしPartだと3つあってどれかわからないのでBaseとリネームしておく

GoalServiceを編集する
まずはゴールの土台にプレイヤーが触れたらコンソールにメッセージが表示されるコードから試してみる
--Workspaceからゴールの土台部分のオブジェクトを取得する
local Workspace = game:GetService("Workspace")
local goalBase = Workspace.World.Goal.Base
--ゴールの土台に何かが触れた時のイベント処理
local function onTouch(otherPart)
--ゴールの土台に触れたのがPlayerだったらメッセージを出す
local player = game.Players:GetPlayerFromCharacter(otherPart.Parent)
if player then
print(player.Name .. " touched the goal!")
end
end
--ゴールの土台にTouchedイベントハンドラを登録
goalBase.Touched:Connect(onTouch)
動作確認する
動作確認の前にメッセージウィンドウを表示しておく
スクリプト内のprint()文の内容はここに出力される
表示タブに出力ウィンドウを表示するボタンがあるので有効にする

ゴールを踏むと出力ウィンドウにメッセージが表示された

メッセージの右側に(x12)と出ているのは、同じメッセージが連続して12回表示されたという意味だ
ちょこっと触れただけで12回もコールされてしまった
2回目以降は無視するような仕組みをいれないとだめかもしれない
タッチイベントが発生したら1秒間はウェイトを置くようにした
--Workspaceからゴールの土台部分のオブジェクトを取得する
local Workspace = game:GetService("Workspace")
local goalBase = Workspace.World.Goal.Base
local debounce = false -- デバウンス状態を追跡する変数
--ゴールの土台に何かが触れた時のイベント処理
local function onTouch(otherPart)
--ゴールの土台に触れたのがPlayerだったらメッセージを出す
local player = game.Players:GetPlayerFromCharacter(otherPart.Parent)
if player and not debounce then
debounce = true -- デバウンスを有効にする
print(player.Name .. " touched the goal!")
wait(1) -- 1秒間デバウンスを有効にする
debounce = false
end
end
--ゴールの土台にTouchedイベントハンドラを登録
goalBase.Touched:Connect(onTouch)
これで、最初の1回だけに反応するようになった
リスポーンさせる
ゴールについたらスタート地点に戻す処理を考える
破棄されたキャラクターはシステムが自動的にリスポーンするらしいので、キャラクターを破棄すればいい
character:Destroy()
を呼ぶことで破棄される
--Workspaceからゴールの土台部分のオブジェクトを取得する
local Workspace = game:GetService("Workspace")
local goalBase = Workspace.World.Goal.Base
local debounce = false -- デバウンス状態を追跡する変数
function respawnPlayer(player)
-- プレイヤーの現在のCharacterを取得
local character = player.Character
-- Characterが存在する場合は削除
if character then
character:Destroy()
end
-- 新しいCharacterが自動的に生成されるのを待つ
player:LoadCharacter()
end
--ゴールの土台に何かが触れた時のイベント処理
local function onTouch(otherPart)
--ゴールの土台に触れたのがPlayerだったらメッセージを出す
local player = game.Players:GetPlayerFromCharacter(otherPart.Parent)
if player and not debounce then
debounce = true -- デバウンスを有効にする
print(player.Name .. " touched the goal!")
wait(2) -- 2秒間デバウンスを有効にする
respawnPlayer(player)
debounce = false
end
end
--ゴールの土台にTouchedイベントハンドラを登録
goalBase.Touched:Connect(onTouch)
クリア演出をつける
ゴールした時に画面に”Goal”と画面に表示してみる
ゴールにプレイヤーが到達したかどうかを判定するのはサーバー側の処理だったが、GUIの制御はクライアント側の処理になる
サーバーからクライアントにそれを伝える仕組みが必要だ
手順としては
StarterGuiに”Goal”ロゴスクリーンを作成する
ReplicatedStorageにサーバーからクライアントにゴールしたかどうか知らせるイベントを作成する
StarterGuiにGoalスクリーンを表示するスクリプトを追加する
サーバー側のGoalServiceからクライアントにゴールしたことを伝える
Goalロゴスクリーンを作成する
エクスプローラーでStarterGuiの下にScreenGuiを追加し、ScreenGuiの下にTextLabelを追加する
TextLabelはGoalTextLabelとリネームしておく

GoalTextLabelのプロパティの調整をする
AnchorPointは画面中央にロゴを表示するために必須な項目で、それ以外はいろいろ好きに調整すれば大丈夫だと思う
AnchorPoint:(0.5, 0.5)
BackgroundTransparency:0
FontFace:LUCKIEST GUY
Text:Goal !!
TextColor3:[213,177,104]
TextScaler:チェック
TextStrokeTransparency:0

GoalTextLabelのサイズと位置を画面の中央になるように調整する

調整が完了したら、VisibleをOFFにして非表示状態にしておく
サーバー→クライアントイベントの作成
ReplicatedStorageの下にRemoteEventを追加しShowGoalMessageRemoteEventとリネームしておく

ゴールロゴを表示するスクリプトを作成する
作成したGoalTextLabelの下にLocalScriptを追加する

スクリプトを編集する
local textLabel = script.Parent
-- GUIを表示する関数
local function showGoalMessage()
-- テキストを表示
textLabel.Visible = true
wait(2) -- 2秒待つ
textLabel.Visible = false
end
-- サーバーからのイベントをリスン
game.ReplicatedStorage.ShowGoalMessageRemoteEvent.OnClientEvent:Connect(showGoalMessage)
ShowGoalMessageRemoteEventが発生したらshowGoalMessage()を呼ぶ
サーバースクリプトのGoalServiceにShowGoalMessageRemoteEventを発生させる
remoteEvent:FireClient(player) -- GUI表示イベントをクライアントに送信
GoalService全体ではこうなる
--Workspaceからゴールの土台部分のオブジェクトを取得する
local Workspace = game:GetService("Workspace")
local goalBase = Workspace.World.Goal.Base
local debounce = false -- デバウンス状態を追跡する変数
local remoteEvent = game.ReplicatedStorage.ShowGoalMessageRemoteEvent
function respawnPlayer(player)
-- プレイヤーの現在のCharacterを取得
local character = player.Character
-- Characterが存在する場合は削除
if character then
character:Destroy()
end
-- 新しいCharacterが自動的に生成されるのを待つ
player:LoadCharacter()
end
--ゴールの土台に何かが触れた時のイベント処理
local function onTouch(otherPart)
--ゴールの土台に触れたのがPlayerだったらメッセージを出す
local player = game.Players:GetPlayerFromCharacter(otherPart.Parent)
if player and not debounce then
debounce = true -- デバウンスを有効にする
print(player.Name .. " touched the goal!")
remoteEvent:FireClient(player) -- GUI表示イベントをクライアントに送信
wait(2) -- 2秒間デバウンスを有効にする
respawnPlayer(player)
debounce = false
end
end
--ゴールの土台にTouchedイベントハンドラを登録
goalBase.Touched:Connect(onTouch)

ひとまずこんな感じかな
次回はステージ本格的に作成しようと思う