見出し画像

[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の制御はクライアント側の処理になる
サーバーからクライアントにそれを伝える仕組みが必要だ

手順としては

  1. StarterGuiに”Goal”ロゴスクリーンを作成する

  2. ReplicatedStorageにサーバーからクライアントにゴールしたかどうか知らせるイベントを作成する

  3. StarterGuiにGoalスクリーンを表示するスクリプトを追加する

  4. サーバー側のGoalServiceからクライアントにゴールしたことを伝える


Goalロゴスクリーンを作成する

エクスプローラーでStarterGuiの下にScreenGuiを追加し、ScreenGuiの下にTextLabelを追加する
TextLabelGoalTextLabelとリネームしておく

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()を呼ぶ


サーバースクリプトのGoalServiceShowGoalMessageRemoteEventを発生させる

		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)



ひとまずこんな感じかな

次回はステージ本格的に作成しようと思う


この記事が参加している募集

この記事が気に入ったらサポートをしてみませんか?