スポーン は、エクスペリエンスでオブジェクトまたはキャラクターを作成するプロセスで、 リスポーン は、キャラクターの体力がゼロになるなど、エクスペリエンスに再び参加するときにオブジェクトまたはキャラクターをエクスペリエンスに追加するプロセスです。��
このチュートリアルのセクションでは、サンプルレーザータグエクスペリエンス を参照として、スポーンとリスポーンを処理するために Roblox の内蔵機能を使用する方法を教えています。これには、スクリプトガイドが含まれます:
- プレイヤーがチームのスポーンゾーンにのみスポーンできるように、スポーン場所を構成します。
- 新しいプレイヤーとそのキャラクターをラウンドに追加すると、エクスペリエンスに参加するようになります。
- プレイヤーがスポーンし、リスポーンするとダメージを防ぐフォースフィールドをカスタマイズします。
- ゲームプレイが適切な時間に正しく機能するように、クライアントステートを処理します。
- ラウンドからタグアウトした後、キャラクターをリスポーンする。
- ゲームプレイとキャラクターパラメータの設定に関する小さな、雑多のアクションを実行する。
このセクションには、スクリプトコンテンツがたくさん含まれていますが、エクスペリエンスを作成するときにすべてをスクリプトで書くのではなく、既存のコンポーネントを活用し、迅速にイテレートし、ビジョンに対応するカスタム実装を見つけることを促します。このセクションを完了すると、ポイントを追跡し、モ
スポーン場所を構成する
今すぐエクスペリエンスをプレイテストすると、緑チームのスポーンゾーンの SpawnLocation オブジェクト、またはピンクチームのスポーンゾーンの SpawnLocation オブジェクトのいずれかにランダムにスポーンします。これは、プレイヤーがそれ��
この問題を解決するために、サンプルレーザータグエクスペリエンスは、<a href="https://www.nielsen.com/Resources/WhitePaper/WhitePaper.aspx" target="_blank"> Class.SpawnLocation.Neutral|Neutral</a> プロパティセッ
プレイヤーがエクスペリエンスに参加すると、 ServerScriptService > ゲームプレイ > ラウンド > 1>spongePlayersInMap1> チェックを見て、どれだけのプレイヤーがそれぞれのチームにいるかを確認し、最小のプレイヤーをチームに返します。
spawnPlayersInMap
local function getSmallestTeam(): Team
local teams = Teams:GetTeams()
-- 最小から最大まで、チームを年齢でソートする
table.sort(teams, function(teamA: Team, teamB: Team)
return #teamA:GetPlayers() < #teamB:GetPlayers()
end)
-- 最小限のチームを返す
return teams[1]
end
チームに最小限のプレイヤーを知ったことで、そのチームにプレイヤーをソートし、 Player.Neutral プロパティを false に設定して、プレイヤーがチームのスポーン場スポーン地点に生成し、その後 PlayerState に設定し、チュートリアル
spawnPlayersInMap
local function spawnPlayersInMap(players: { Player })
for _, player in players do
player.Team = getSmallestTeam()
player.Neutral = false
player:SetAttribute(PlayerAttribute.playerState, PlayerState.SelectingBlaster)
task.spawn(function()
player:LoadCharacter()
end)
end
end
ワークスペース > ワールド > マップ > スポーン > スポーン場所 > ニュートラルスポーン > スポーン地点 >
たとえば、ラウンドがアクティブである場合、Neutral プロパティは false に設定され
- Class.Player.Neutral プロパティを true に設定して、Player.Team を自動的に nil にリセットして、スポーン場所の Neutral プロパティを 1> true1> に設定します。これにより、ラウンドがアクティブでない
- 変更します PlayerState を InLobby に変更して、プレイヤーのブラスターとファーストパーソン UI ビジュアルを削除します。
中立スポーンゾーンとその機能についての詳細は、チュートリアルの次のセクションで [Add Rounds] を参照してください。
ロビーにプレイヤーをスポーンする
local function spawnPlayersInLobby(players: { Player })
for _, player in players do
player.Neutral = true
player:SetAttribute(PlayerAttribute.playerState, PlayerState.InLobby)
task.spawn(function()
player:LoadCharacter()
end)
end
end
新しいプレイヤーを接続する
Studio の Luau コードは、イベントを主導するため、スクリプトは Roblox サービスからのイベントをリスニングし、その後機能を呼び出します。たとえば、新しいプレイヤーをマルチプレイヤーエクスペリエンスに追加するときは、プレイヤーが正常に接続するために必要なすべてのイベントを処理する必要があ
Players.PlayerAdded:Connect は、エクスペリエンス内の複数のスクリプトの一部です。 Ctrl/Commands+Shift+F のショートカットを使用し、Players.PlayerAdded:Connect を検索すると、結果はエクスペリエンスの初期設定を理解するのに役立ちます。
デモを示すには、 ServerScriptService > SetupHumanoid を開きます。Player と1> Class.Player.Character|Character1> の違いは、このスクリプトの理解に不可欠な要素です:
- プレイヤーは接続されたクライアントであり、キャラクターは Class.Humanoid モデルです。
- プレイヤーはブラスターを選択し、リーダーボードに追加される必要があります。キャラクターはブラスターをスポーンし、受信する必要があります。
SetupHumanoid は、プレイヤーがキャラクターを持っているかどうかを即座にチェックします (ただ参加しました) またはそうで
設定HumanoidAsync
local function setupHumanoidAsync(player: Player, humanoid: Humanoid)
humanoid.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.Subject
humanoid.NameDisplayDistance = 1000
humanoid.HealthDisplayDistance = 1000
humanoid.NameOcclusion = Enum.NameOcclusion.OccludeAll
humanoid.HealthDisplayType = Enum.HumanoidHealthDisplayType.AlwaysOn
humanoid.BreakJointsOnDeath = false
humanoid.Died:Wait()
onHumanoidDied(player, humanoid)
end
このスクリプトの重要なメモは、プロパティが完全にオプションであることです。つまり、機能の最初の 6 行を削除すると、エクスペリエンスはまだ機能します。機能要件ではなく、各プロパティを通じて、ゲームプレイ目標に一致するデザイン決定を行うことができます。たとえば:
- キャラクター名をより近くの距離で表示したい場合は、Humanoid.NameDisplayDistance の値を減少します。
- 100% 以下の場合にのみ、キャラクターの健康を表示するために Humanoid.HealthDisplayType を ダメージを受けたときに表示 に設定します。
- 如果角色の体力が 0 になるときに分解するようにしたい場合は、Humanoid.BreakJointsOnDeath を True に設定します。
これらのプロパティの値を変更すると、新しい設定の影響を確認するためにプレイテストすることは重要です。クライアントとサーバーセクションのテストタブで、プレイヤーが新しい設定の影響を確認できます。
Another example of the Players.PlayerAdded:Connect 事件は ServerScriptService > PlayerStateHandler の中にあります。前の例と同じように、 1> PlayerStateHandler
PlayerStateHandler
local function onPlayerAdded(player: Player)
player.CharacterAdded:Connect(function()
if not player.Neutral then
player:SetAttribute(PlayerAttribute.playerState, PlayerState.SelectingBlaster)
onPlayerStateChanged(player, PlayerState.SelectingBlaster)
end
end)
PlayerStateHandler の一つの特定の変数は、attributeChangedConnectionByPlayer を含むすべてのプレイヤーとそのConnections を1>GetAttributeChangedSignal</
PlayerStateHandler
local attributeChangedConnectionByPlayer = {}
local function onPlayerAdded(player: Player)
-- プレイヤー状態のすべての将来の更新を処理する
attributeChangedConnectionByPlayer[player] = player
:GetAttributeChangedSignal(PlayerAttribute.playerState)
:Connect(function()
local newPlayerState = player:GetAttribute(PlayerAttribute.playerState)
onPlayerStateChanged(player, newPlayerState)
end)
end
-- プレイヤーが去ると変更されたアトリビューションの接続から切断する
local function onPlayerRemoving(player: Player)
if attributeChangedConnectionByPlayer[player] then
attributeChangedConnectionByPlayer[player]:Disconnect()
attributeChangedConnectionByPlayer[player] = nil
end
end
You can see that both connected functions in onPlayerAdded() call onPlayerStateChanged() . During initial setup after a player sorts into a team, onPlayerAdded() sets 1> PlayerState
PlayerStateHandler
local function onPlayerStateChanged(player: Player, newPlayerState: string)
-- 「プレイ」状態のみ「準備」モードになります
local newBlasterState = if newPlayerState == PlayerState.Playing then BlasterState.Ready else BlasterState.Disabled
-- プレイヤーがプレイ開始時に破壊フォースフィールドのロジックをスケジュール
if newPlayerState == PlayerState.Playing then
scheduleDestroyForceField(player)
end
player:SetAttribute(PlayerAttribute.blasterStateServer, newBlasterState)
end
スポーン地点憩ポイントを追加するか、単に
フォースフィールドをカスタマイズ
カスタム実装を使用する代わりに、サンプルレーザータグエクスペリエンスは Studio の内蔵 ForceField クラスを使用して、プレイヤーがブラスターを選択している間
Similar to setupHumanoidAsync , most of the lines in ForceFieldClientVisuals はオプションです。たとえ、次のスクリプトのように機能のコンテンツをコメントしても、エクスペリエンスはデフォルトのスパークルフォースフィールドを使用し、 StarterGui > 1>ForceFieldGui</
ForceFieldClientVisuals のプロパティをコメントアウト
local function onCharacterAddedAsync(character: Model)
-- local forceField = キャラクター:WaitForChild("ForceField", 3)
-- ForceField でない場合は
-- 戻る
-- 終了
-- forceField.Visible = フォースフィールドが表示されない
-- localPlayer.PlayerGui:WaitForChild("ForceFieldGui")。有効化済み
-- forceField.Destroying:Wait()
-- localPlayer.PlayerGui.ForceFieldGui.Enabled = false
end
カスタムフォースフィールドが新しい ParticleEmitter ではなく、GUI であるため、ForceFieldClientVisuals スクリプトは、各プレイヤーのビジュアルのみに影響し、Class.ForceField.Visible のビジュアルは影響しません。
フォースフィールドは、敵のプレイヤーに気を遣うことなくスポーンからリスポーンまでのプレイヤーに十分な時間を提供するために便利ですが、最終的にメインレーザータグゲームプレイに必要ないことを確認するためには、フォースフィールドを削除する必要があります。フォースフィールドを削除するスクリプトは、
- プレイヤーがブラスターを選択した後、フォースフィールドはプレイヤーが周囲に慣れるように長く続く必要があります。
- このアクセラレーション時間中、フォースフィールドは優位ではなくなりますので、プレイヤーがブラスターを爆破するときには消える必要があります。
- フォースフィールドは、プレイヤーがキャラクターをリセットする前に、またはフォースフィールドの時間切れになる前に消える必要があります。
これらのチェックは、scheduleDestroyForceFieldスクリプトの呼び出しの endForceField() で、これらの条件のために endForceField を破壊します。
スケジュールDestoryForceField
-- プレイヤーが爆破する場合は、終了フォースフィールド
local blasterStateAttribute = getBlasterStateAttribute()
attributeChangedConnection = player:GetAttributeChangedSignal(blasterStateAttribute):Connect(function()
local currentBlasterState = player:GetAttribute(blasterStateAttribute)
if currentBlasterState == BlasterState.Blasting then
endForceField()
end
end)
-- プレイヤーがリセットすると、終了フォースフィールド
characterRespawnedConnection = player.CharacterRemoving:Connect(endForceField)
-- 8秒後にフォースフィールドを終了
task.delay(MAX_FORCE_FIELD_TIME, endForceField)
endForceField() には、if のように奇妙な forceFieldEnded のステートが含まれています。チェックは連続して実行されるため、スクリプトは 0> endForceFieldEnded0> のブールーンを 2 回または 3 回呼び出す可能性
スケジュールDestoryForceField
local function endForceField()
if forceFieldEnded then
return
end
forceFieldEnded = true
attributeChangedConnection:Disconnect()
characterRespawnedConnection:Disconnect()
destroyForceField(player)
end
クライアントステートを処理する
このセクションのほとんどは ServerScriptService > PlayerStateHandler に焦点を当てていますが、ReplicatedStorage には同じ名前の別のスクリプトがあります。理由はクライアント-サーバーアーキテクチャです:
クライアントはプレイヤーの状態情報を理解して、リアルタイムで適切に応答できるようにする必要があります。たとえば、正しいユーザーインターフェイス要素を表示するか、プレイヤーが移動して爆発することを有効にするなどです。
同じ情報が必要ですので、サーバーがエクスプロイトを防止できます。たとえば、サーバーはチャラクターをスポーンしたり、装備したりするなどのアクションを実行するためにプレイヤーステートが必要です。これは、このスクリプトが ReplicatedStorage にある理由で、クライアント側の場所ではありません。
このコアロジックを見るには、 ReplicatedStorage > PlayerStateHandler のスクリプトを確認してください。これは、ユーザーの現在の状態を確認し、その状態に対応するアクションを処理する適切な関数を呼び出します。
PlayerStateHandler
local function onPlayerStateChanged(newPlayerState: string)
if newPlayerState == PlayerState.SelectingBlaster then
onSelectingBlaster()
elseif newPlayerState == PlayerState.Playing then
onPlaying()
elseif newPlayerState == PlayerState.TaggedOut then
onTaggedOut()
elseif newPlayerState == PlayerState.InLobby then
onInLobby()
else
warn(`Invalid player state ({newPlayerState})`)
end
end
すべてのイベントのレポートは、このスクリプトでロジックでグループ化されています、因為プレイヤーのコントロール、カメラの移動、そしてどの UI レイヤーが表示されるかを有効化または無効化するための同様の動作が必要になります。たとえば
PlayerStateHandler
local function onSelectingBlaster()
togglePlayerCamera(true)
togglePlayerMovement(false)
setGuiExclusivelyEnabled(playerGui.PickABlasterGui)
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Disabled)
end
The onPlaying() 関数は同様に簡単です。それは、移動、メインのヘッドアップディスプレイ (HUD) への移行を有効にし、ブラスターを有効にし、サーバーと同じフォースフィールド機能を呼び出します。
PlayerStateHandler
local function onPlaying()
togglePlayerMovement(true)
setGuiExclusivelyEnabled(playerGui.HUDGui)
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Ready)
scheduleDestroyForceField()
end
キャラクターをリスポーン
サンプルレーザータグエクスペリエンスは、onTaggedOut() 状態のリプリケートストレージ > プレイヤーステートハンドラー</
PlayerStateHandler
local function onTaggedOut()
-- タグアウト中にコントロールを無効にする
togglePlayerMovement(false)
togglePlayerCamera(false)
setGuiExclusivelyEnabled(playerGui.OutStateGui)
-- タグアウト中にブラスターを無効にする
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Disabled)
end
この動作をテストしたい場合は、Esc を押す、 設定 タブに移動し、 キャラクターのリセット ボタンをクリックします。注意、リスポーン画面をトリガーすると、移動、カメラを回転、ブラスターを爆破できません。
このスクリプトは、実際にキャラクターをリスポーンするわけではな
プレイヤーがラウンドにリスポーンすると、SpawnLocation.TeamColor プロパティにより、チームのスポーン場所にリスポーンします。SetupHumanoid をカスタマイズするには、Players.RespawnTime のトップに次のラインを追加できます。1>Class.
ヒューマノイドをセットアップ
local Players = game:GetService("Players")Players.RespawnTime = 10 -- new line, in seconds
その他のセットアップ
インターミッションレーザータグのサンプル体験は、最初のセットアップの一部として、ささやかで重要なステップをいくつか実行します:
エクスペリエンスには、 StarterPlayer という名前の空のスクリプトが含まれています > StarterCharacterScripts > Health が、デフォルトの Roblox 体力再生を無効にします。このプロパティの動作についての説明は、1> Class.Humanoid.Health1> を参照してください。
エクスペリエンスは、StarterPlayer.CameraMode.LockFirstPerson プロパティを設定することで、ユーザーが 1人目から 3人目のカメラの間で変更できるようにします。ユーザーが 1人目から 3人目のカメラの間で変更できるようにするには、コントロールと UI を調整して、視点の変更を補償するためにプロパティ
エクスペリエンスは、「ポイント」の単位で Roblox リーダーボードを使用し、プレイヤーがタグを付けるたびに獲得することができるコンフィグを提供します。 ServerScriptService > 設
プレイヤーがスポーンできるようになり、ブラスターを選択し、1人称のビューから狙いを定めるので、次のセクションでは、ラウンドベースのゲームプレイを作成するスクリプトについて説明します。