デザインの実装は、組み込みおよびカスタムUI要素を使用して、スタジオでワイヤーフレームを作成するプロセスです。このチュートリアルのエキサイティングなステップでは、すべてのデザインと努力が一つの一貫したワークフローセットにまとめられ、プレイヤーのインタラクションの準備が整います。
サンプルレーザータグゲーム .rbxlファイルを参照として、このユーザーインターフェースデザインカリキュラムのこのセクションでは、UI計画を実現する方法を示します。以下のガイダンスが含まれています:
- UIアセットライブラリからアセットIDを取得して、サンプルレーザータグゲームのUIコンポーネントを再現できるようにします。
- スタジオ内でさまざまなデバイスをエミュレートして、異なる画面やアスペクト比でUIがどのように表示されるかを確認します。
このセクションのテクニックを確認した後は、自分のプロジェクトに適用して、プレイヤーがゲーム内でできることをナビゲートするのに役立つエキサイティングなUIコンポーネントを作成できます。
アセットライブラリを取得する
アセットライブラリは、簡単にアクセスして再利用できるアセットのコレクションです。あなたのプロジェクトで使用するアセットライブラリは、クリエイターストアから取得でき、9つの2D個別UI要素アセットと、このチュートリアルのこのセクションで作成している目的、ブラスターセレクター、およびプレイヤー情報コンポーネントの最終バージョンが含まれています。

rbxassetid://14309094777

rbxassetid://14309094641

rbxassetid://14309678581

rbxassetid://14304828203

rbxassetid://14304827304

rbxassetid://14309678701

rbxassetid://14304826876

rbxassetid://14304827147

rbxassetid://18308375067

rbxassetid://18308372597

rbxassetid://14400935532

rbxassetid://14401148777

rbxassetid://14462567943

rbxassetid://14309187282

rbxassetid://14309518632
アセットライブラリをインベントリからゲームに取得するには:
アセットライブラリをインベントリに追加します。
- クリエイターストアのアセットライブラリの詳細ページに移動します。
- 右上隅で、モデルを取得ボタンをクリックします。アセットライブラリがインベントリに追加され、プラットフォーム上の任意のプロジェクトでこれらのアセットを再利用できます。
スタジオで、ホームタブに移動し、ツールボックスボタンをクリックします。ツールボックスウィンドウが開きます。

ツールボックスウィンドウで、インベントリタブをクリックします。マイモデルのソートが表示されます。

ドロップダウンメニューをクリックし、マイパッケージのソートを選択します。
最終画面UIコンポーネントタイルをクリックし、エクスプローラーウィンドウで完了したコンポーネントを選択し、それをStarterGuiサービスにドラッグします。これで、最終コンポーネントのいずれかを有効にして、そのデザインを参照できます。
デバイスをエミュレートする
スタジオのデバイスエミュレーターを使用すると、プレイヤーがさまざまなデバイスでUIをどのように見るか、どのようにインタラクトするかをテストできます。このツールは実装プロセスの重要な部分であり、スタジオのビューポートのアスペクト比がプレイヤーがゲームにアクセスするために使用する画面のアスペクト比を必ずしも反映しないため、UIがすべてのデバイスで読みやすく、アクセス可能であることが重要です。
たとえば、さまざまな画面サイズでUIをテストしないと、大きな画面を持つプレイヤーはテキストを読めなかったり、アイコンを解読できなかったりする可能性があり、小さな画面を持つプレイヤーはUI要素が表示の多くのスペースを占めるために3D空間を見ることができないかもしれません。
さまざまな画面サイズでUIをエミュレートするには:
スタジオのテストメニューから、デバイスエミュレーターをオンにします。
解像度のドロップダウンで、実際の解像度を選択します。これにより、エミュレートしているデバイス上でUI要素の真の解像度を見ることができます。

デバイスのドロップダウンで、電話、タブレット、デスクトップ、およびコンソールセクション内の少なくとも1つのデバイスを選択します。

ScreenGuiオブジェクトを作成する
すべてのプレイヤーの画面にUI要素を表示するには、ScreenGuiオブジェクトをStarterGuiサービスに作成できます。ScreenGuiオブジェクトは、画面上のUIの主要なコンテナであり、StarterGuiサービスは、プレイヤーがゲームに入るときにその内容を各プレイヤーのPlayerGuiコンテナにコピーします。
複数のScreenGuiオブジェクトを作成して、ゲームプレイ中にUI要素のグループを文脈に応じて整理して表示できます。たとえば、サンプルレーザータグゲームには、プレイヤーがゲームのメインユーザーフロー中に異なる条件を満たすまで最初は無効になっている5つの別々のScreenGuiオブジェクトが含まれています:
- HUDGui - プレイヤーがラウンド中にアクティブなときに、目的や各チームの合計ポイントなど、ゲームプレイに関する重要な情報を表示します。
- PickABlasterGui - プレイヤーがラウンドを開始または再参加するときに、すべてのブラスターの選択肢を表示します。
- ForceFieldGui - プレイヤーがブラスターを選択しているときや、一時的に無敵のときに六角形のグリッドを表示します。
- OutStateGui - プレイヤーがタグ付けされたときに画面の周りに暗いボーダーを表示します。
- RoundResultsGui - ラウンドで勝ったチームに関する情報を持つ暗いオーバーレイを画面の上に表示します。
ScreenGuiオブジェクトを作成した後は、各コンテナの目的に応じてその子GuiObjectsを作成およびカスタマイズできます。次のセクションでは、サンプルレーザータグゲームでプレイヤーが成功するために知っておくべき3つの情報カテゴリのUI要素を実装する方法を学びます。プロセスの任意の部分を自分のゲームの仕様に合わせて調整できます。
ScreenGuiオブジェクトを作成するには:
エクスプローラーウィンドウで、StarterGuiサービスにカーソルを合わせ、**⊕**アイコンをクリックします。文脈メニューが表示されます。
ScreenGuiを挿入します。

子UI要素の文脈に応じてScreenGuiの名前を変更します。
すべてのプレイヤーの画面に表示する必要がある各UI要素のグループについて、このプロセスを繰り返します。

目的UI
ワイヤーフレームを作成するの視覚的階層のベストプラクティスに従って、このセクションではゲームの目的に関連するすべての画面上のUI要素を実装する方法を教えます。このUI要素のグループは、ゲームに勝つために最も重要な目的と各チームのポイントがあるため、画面の上部に近い位置に配置されます。

たとえば、サンプルはプレイヤーがラウンドで成功するために何をする必要があるかを知るために参照する目的UIコンポーネントを提供します。プレイヤーが敵チームのメンバーをタグ付けしてポイントを獲得すると、このコンポーネントはヘッダーのプロンプト内で全体の目標に対する各チームのスコアを追跡します。ポイントを追跡するために協力するすべてのクライアントおよびサーバースクリプトの高レベルのレビューについては、ゲームプレイスクリプティングカリキュラムのポイントを追跡するを参照してください。

サンプルレーザータグゲーム内で目的UIを正確に再現するには:
コンポーネント全体のコンテナを作成します。
HUDGui ScreenGuiオブジェクトにFrameを挿入します。
- エクスプローラーウィンドウで、StarterGuiサービスに移動します。
- 子HUDGuiオブジェクトにカーソルを合わせ、⊕アイコンをクリックします。文脈メニューが表示されます。
- 文脈メニューから、Frameを挿入します。

新しいFrameを選択し、プロパティウィンドウで、
- AnchorPointを0.5, 0に設定して、フレームの原点を上部中央に設定します(フレームの左から右に50%、上から下に0%)。
- BackgroundTransparencyを1に設定して、フレームの背景を完全に透明にします。
- Positionを{0.5, 0},{0.03, 0}に設定して、画面の上部中央にフレームを配置します(画面の左から右に50%、上から下に3%)。
- Sizeを{0.5, 0},{0.13, 0}に設定して、フレームの要素が画面の上部の大部分を占めてプレイヤーの注意を引くようにします(横に50%、縦に13%)。
- NameをObjectiveに設定します。

- OPTIONALObjectiveにUIAspectRatioConstraintを挿入して、ラベルのアスペクト比がプレイヤーの画面サイズに関係なく同じままになるようにします。サンプルでは、UIAspectRatioConstraint.AspectRatioプロパティを7に設定しています。
目的のプロンプトオブジェクトのためのコンテナを作成します。
ObjectiveにFrameを挿入します。
新しいFrameを選択し、プロパティウィンドウで、
- AnchorPointを0.5, 0に設定して、フレームの原点を上部中央に設定します(フレームの左から右に50%、上から下に0%)。
- BackgroundTransparencyを1に設定して、フレームの背景を完全に透明にします。
- Positionを{0.5, 0},{0, 0}に設定して、コンテナの中央にフレームを配置します(親フレームの左から右に50%、上から下に0%)。
- Sizeを{1, 0},{0.67, 0}に設定して、選択UIコンポーネントがコンテナの上から下の約半分を占めるようにします(親フレームの100%横、67%縦)。
- NameをObjectiveDisplayに設定します。

タイトル要素を作成します。
ObjectiveDisplayにImageLabelを挿入します。
ImageLabelを選択し、プロパティウィンドウで、
- AnchorPointを0.5, 1に設定して、ラベルの原点を下部中央に設定します(ラベルの左から右に50%、上から下に100%)。
- BackgroundTransparencyを1に設定して、ラベルの背景を完全に透明にします。
- LayoutOrderを-1に設定します。
- Positionを{0.5, 0},{0.34, 0}に設定して、フレームの上部中央にラベルを配置します(親フレームの左から右に50%、上から下に34%)。
- Sizeを{0.46, 0},{0.34, 0}に設定して、プロンプトエリアをフレームのほぼ半分に広げます(親フレームの46%横、34%縦)。
- NameをHeaderに設定します。
- Imageをrbxassetid://14304828123に設定して、台形を表示します。
- ImageTransparencyを0.15に設定して、ヘッダーを半透明にします。

- OPTIONALImageLabelにUIAspectRatioConstraintを挿入して、ラベルのアスペクト比がプレイヤーの画面サイズに関係なく同じままになるようにします。サンプルでは、UIAspectRatioConstraint.AspectRatioプロパティを13.781に設定しています。
HeaderにTextLabelを挿入して、タイトルを表示します。
新しいラベルを選択し、プロパティウィンドウで、
- AnchorPointを0.5, 0.5に設定して、新しいラベルの原点を中央に設定します(ラベルの左から右に50%、上から下に50%)。
- BackgroundTransparencyを1に設定して、ラベルの背景を完全に透明にします。
- Positionを{0.5, 0},{0.5, 0}に設定して、ラベルを親ラベルの中央に移動します(親ラベルの左から右に50%、上から下に50%)。
- Sizeを{0.62, 0},{0.55, 0}に設定して、テキストスペースを親ラベルの半分以上に広げます(親ラベルの62%横、55%縦)。
- NameをHeaderTextLabelに設定します。
- FontFaceをMontserratに設定して、未来的な美学に合わせます。
- WeightをMediumに設定して、フォントを太くします。
- TextをOBJECTIVEに設定します。
- TextScaledを有効にします。

プロンプト要素を作成します。
ObjectiveDisplayにImageLabelを挿入します。
ImageLabelを選択し、プロパティウィンドウで、
- AnchorPointを0.5, 1に設定して、ラベルの原点を下部中央に設定します(ラベルの左から右に50%、上から下に100%)。
- BackgroundTransparencyを1に設定して、ラベルの背景を完全に透明にします。
- Positionを{0.5, 0},{1, 0}に設定して、親フレームの下部中央にラベルを移動します(親フレームの左から右に50%、上から下に100%)。
- Sizeを{0.89, 0},{0.66, 0}に設定して、テキストスペースを親フレームのほぼ全幅に広げます(親フレームの89%横、66%縦)。
- NameをBodyに設定します。
- Imageをrbxassetid://14304827265に設定して、逆さ台形を表示します。
- ImageColor3を0, 0, 0に設定して、画像を黒に着色します。
- ImageTransparencyを0.3に設定して、ヘッダーを半透明にします。

- OPTIONALImageLabelにUIAspectRatioConstraintを挿入して、ラベルのアスペクト比がプレイヤーの画面サイズに関係なく同じままになるようにします。サンプルでは、UIAspectRatioConstraint.AspectRatioプロパティを13.781に設定しています。
BodyにTextLabelを挿入して、プロンプトを表示します。
新しいラベルを選択し、プロパティウィンドウで、
- AnchorPointを0.5, 0.5に設定して、新しいラベルの原点を中央に設定します(ラベルの左から右に50%、上から下に50%)。
- BackgroundTransparencyを1に設定して、ラベルの背景を完全に透明にします。
- Positionを{0.5, 0},{0.5, 0}に設定して、ラベルを親ラベルの中央に移動します(親ラベルの左から右に50%、上から下に50%)。
- Sizeを{0.85, 0},{0.39, 0}に設定して、テキストスペースを親ラベルの半分以上に広げます(親ラベルの85%横、39%縦)。
- NameをBodyTextLabelに設定します。
- FontFaceをMontserratに設定して、未来的な美学に合わせます。
- WeightをMediumに設定して、フォントを太くします。
- TextColor3を255, 255, 255に設定して、暗い背景に対してテキストを白くします。
- Textを**対戦相手をタグ付けしてポイントを獲得しよう!最初のチームが%dポイントを獲得したら勝ち。**に設定します。
- TextScaledを有効にします。

目的のチームカウンターのためのコンテナを作成します。
ObjectiveにFrameを挿入します。
新しいFrameを選択し、プロパティウィンドウで、
- AnchorPointを0.5, 1に設定して、フレームの原点を下部中央に設定します(フレームの左から右に50%、上から下に100%)。
- BackgroundTransparencyを1に設定して、フレームの背景を完全に透明にします。
- Positionを{0.5, 0},{1, 0}に設定して、コンテナの下部中央にフレームを配置します(親フレームの左から右に50%、上から下に100%)。
- Sizeを{0.44, 0},{0.27, 0}に設定して、選択UIコンポーネントがコンテナの左から右の約半分を占めるようにします(親フレームの44%横、27%縦)。
- NameをTeamPointCounterに設定します。

チームカウンターのパディングを作成します。
- ステップ5のフレームにUIListLayoutオブジェクトを挿入します。
- UIListLayoutオブジェクトを選択し、プロパティウィンドウで、
- Paddingを0.025, 0に設定して、将来のチームカウンターの間にスペースを提供します。
- FillDirectionをHorizontalに設定して、各チームカウンターが隣り合って表示されるようにします。
- HorizontalAlignmentをCenterに設定して、各チームカウンターが互いに中央に揃うようにします。
グリーンチームカウンター要素を作成します。
TeamPointCounterにImageLabelを挿入します。
ImageLabelを選択し、プロパティウィンドウで、
- BackgroundTransparencyを1に設定して、ラベルの背景を完全に透明にします。
- Positionを{0.5, 0},{1, 0}に設定して、親フレームの下部中央にラベルを移動します(親フレームの左から右に50%、上から下に100%)。
- Sizeを{0.5, 0},{1, 0}に設定して、ラベルを親フレームの半分の幅に広げます(親フレームの50%横、100%縦)。
- NameをTeamACounterに設定します。
- Imageをrbxassetid://14304826831に設定して、方向性のフェードを表示します。
- ImageColor3を88, 218, 171に設定して、画像をミントグリーンに着色します。

このラベルがグリーンチーム用であることを追跡するカスタム属性を設定します。
- プロパティウィンドウで、属性セクションに移動し、プラスアイコンをクリックします。ポップアップダイアログが表示されます。
- 名前フィールドにteamColorと入力します。
- タイプドロップダウンメニューで、BrickColorを選択します。
- 保存ボタンをクリックします。
- 新しいteamColor属性をMintに設定します。
TeamACounterにTextLabelを挿入して、プロンプトを表示します。
新しいラベルを選択し、プロパティウィンドウで、
- AnchorPointを1, 0.5に設定して、新しいラベルの原点を右中央に設定します(ラベルの左から右に100%、上から下に50%)。
- BackgroundTransparencyを1に設定して、ラベルの背景を完全に透明にします。
- Positionを{0.95, 0},{0.5, 0}に設定して、親ラベルの右側にラベルを移動します(親ラベルの左から右に95%、上から下に50%)。
- Sizeを{0.85, 0},{0.39, 0}に設定して、テキストスペースを親ラベルの半分以上に広げます(親ラベルの85%横、39%縦)。
- FontFaceをMontserratに設定して、未来的な美学に合わせます。
- WeightをBoldに設定して、フォントを太くします。
- TextColor3を255, 255, 255に設定して、暗い背景に対してテキストを白くします。
- Textを**-**に設定します。
- TextScaledを有効にします。
- TextXAlignmentをRightに設定します。

TextLabelにUIStrokeオブジェクトを挿入し、プロパティウィンドウでColorを8, 78, 52に設定して、ダッシュをダークグリーンのストロークでアウトラインします。

ピンクチームカウンター要素を作成します。
TeamAICounterとその子を複製します。
複製したTeamACounterを選択し、プロパティウィンドウで、
- NameをTeamBCounterに設定します。
- Imageをrbxassetid://14305849451に設定して、反対方向の方向性のフェードを表示します。
- ImageColor3を255, 170, 255に設定して、画像をカーネーションピンクに着色します。
- teamColor属性をCarnation Pinkに設定します。
複製したTextLabelをTeamBCounterの子として選択し、プロパティウィンドウで、
- AnchorPointを0, 0.5に設定して、新しいラベルの原点を左中央に設定します(ラベルの左から右に0%、上から下に50%)。
- Positionを{0.05, 0},{0.5, 0}に設定して、親ラベルの左側にラベルを移動します(親ラベルの左から右に5%、上から下に50%)。
- TextXAlignmentをLeftに設定します。
複製したUIStrokeをTeamBCounterの子として選択し、プロパティウィンドウでColorを158, 18, 94に設定して、ダッシュをダークピンクのストロークでアウトラインします。

サンプルレーザータグプレースファイル内の以下のReplicatedStorageスクリプトを参照して、目的のプロンプトをプログラム的に更新し、チームポイントを追跡します。
以下のスクリプトは、setObjectiveやstartSyncingTeamPointsを含むメインヘッドアップディスプレイ(HUD)を設定するために協力するモジュールスクリプトのセットを必要とします。プレイヤーがラウンドに参加し、ブラスターを選択すると、このスクリプトはすべてのHUD UI要素がプレイヤーの状態、デバイス、およびチームのステータスに適切に表示されることを保証します。
local Players = game:GetService("Players")
local setPlayerPortrait = require(script.setPlayerPortrait)
local setPlayerName = require(script.setPlayerName)
local startSyncingTeamColor = require(script.startSyncingTeamColor)
local setObjective = require(script.setObjective)
local setupTouchButtonAsync = require(script.setupTouchButtonAsync)
local startSyncingTeamPoints = require(script.startSyncingTeamPoints)
local disableMouseWhileGuiEnabled = require(script.disableMouseWhileGuiEnabled)
local setupHitmarker = require(script.setupHitmarker)
local localPlayer = Players.LocalPlayer
local gui = localPlayer.PlayerGui:WaitForChild("HUDGui")
setPlayerPortrait(gui)
setPlayerName(gui)
startSyncingTeamColor(gui)
setObjective(gui)
startSyncingTeamPoints(gui)
disableMouseWhileGuiEnabled(gui)
setupHitmarker(gui)
setupTouchButtonAsync(gui)ブラスターUI
ワイヤーフレームを作成するの視覚的階層のベストプラクティスに従って、このセクションではプレイヤーのブラスターに関連するすべての画面上のUI要素を実装する方法を教えます。このUI要素のグループは、画面の中央付近の大部分のスペースを占め、3D空間でのアクションにプレイヤーの注意を引く焦点として機能し、ゲームプレイに最も重要です。

クロスヘア
クロスヘアは、プレイヤーが武器を発射する際に衝撃を与える場所を知らせるUI要素です。このUI要素は、プレイヤーがブラスターを正確に狙い、敵チームのメンバーをタグ付けするために必要な重要なゲームプレイ要件です。
ほとんどのファーストパーソンシューティングゲームと同様に、サンプルレーザータグゲームはクロスヘアを画面の中央に配置して、プレイヤーがアバターを3D空間で移動させる間に静的な焦点を持つことができるようにします。これにより、動きによる吐き気を軽減し、クロスヘアが目立つ一方で、全体の環境に溶け込むことができます。

サンプルレーザータグゲーム内でクロスヘアを正確に再現するには:
HUDGui ScreenGuiオブジェクトにImageLabelを挿入します。
エクスプローラーウィンドウで、StarterGuiサービスに移動します。
子HUDGuiオブジェクトにカーソルを合わせ、**⊕**アイコンをクリックします。文脈メニューが表示されます。
文脈メニューから、ImageLabelを挿入します。

新しいImageLabelを選択し、プロパティウィンドウで、
- Imageをrbxassetid://14400935446に設定します。
- AnchorPointを0.5, 0.5に設定して、ラベルの原点をラベルの中央に設定します(ラベルの左から右に50%、上から下に50%)。
- BackgroundTransparencyを1に設定して、ラベルの背景を完全に透明にします。
- NameをCrosshairに設定します。
- Positionを{0.5,0},{0.5,0}に設定して、ラベルを画面の中央に配置します。
- ScaleTypeをFitに設定して、画像がそのコンテナ内に収まり、さまざまな画面サイズで伸びないようにします。
- OPTIONALCrosshairにUIAspectRatioConstraintを挿入して、ラベルのアスペクト比がプレイヤーの画面サイズに関係なく同じままになるようにします。サンプルでは、UIAspectRatioConstraint.AspectRatioプロパティを0.895に設定しています。
ヒットマーカー
ヒットマーカーは、発射が敵チームの別のプレイヤーに衝撃を与えたときにのみ表示されるUI要素です。クロスヘアと同様に、このUI要素は、プレイヤーが対戦相手をタグ付けする際に成功したことを視覚的にフィードバックするために必要な重要なゲームプレイ要件です。

サンプルレーザータグゲーム内でヒットマーカーを正確に再現するには:
Crosshair ImageLabelオブジェクトにImageLabelを挿入します。
エクスプローラーウィンドウで、StarterGuiサービスに移動します。
子Crosshairオブジェクトにカーソルを合わせ、**⊕**アイコンをクリックします。文脈メニューが表示されます。
文脈メニューから、ImageLabelを挿入します。

新しいImageLabelを選択し、プロパティウィンドウで、
- Imageをrbxassetid://14401148736に設定して、長方形のヒットマーカーアイコンを表示します。
- AnchorPointを0.5, 0.5に設定して、ラベルの原点をラベルの中央に設定します。
- BackgroundTransparencyを1に設定して、ラベルの背景を完全に透明にします。
- Positionを{0.5,0},{0.5,0}に設定して、ラベルを画面の中央に配置します。
- NameをHitmarkerに設定します。
- Sizeを{0.6, 0},{0.06, 0}に設定して、クロスヘアの中央周辺の長方形のサイズを減少させます。
- ImageTransparencyを1に設定して、ヒットマーカーを完全に透明にします。次のステップのスクリプトが、プレイヤーの発射が敵チームの別のプレイヤーに衝撃を与えるたびに透明度を0に戻します。
サンプルレーザータグプレースファイル内の以下のReplicatedStorageスクリプトを参照して、発射が敵チームのプレイヤーに衝撃を与えたときにヒットマーカーをプログラム的に表示します。
以下のスクリプトは、setupHitmarkerを含むメインヘッドアップディスプレイ(HUD)を設定するために協力するモジュールスクリプトのセットを必要とします。プレイヤーがラウンドに参加し、ブラスターを選択すると、このスクリプトはすべてのHUD UI要素がプレイヤーの状態、デバイス、およびチームのステータスに適切に表示されることを保証します。
local Players = game:GetService("Players")
local setPlayerPortrait = require(script.setPlayerPortrait)
local setPlayerName = require(script.setPlayerName)
local startSyncingTeamColor = require(script.startSyncingTeamColor)
local setObjective = require(script.setObjective)
local setupTouchButtonAsync = require(script.setupTouchButtonAsync)
local startSyncingTeamPoints = require(script.startSyncingTeamPoints)
local disableMouseWhileGuiEnabled = require(script.disableMouseWhileGuiEnabled)
local setupHitmarker = require(script.setupHitmarker)
local localPlayer = Players.LocalPlayer
local gui = localPlayer.PlayerGui:WaitForChild("HUDGui")
setPlayerPortrait(gui)
setPlayerName(gui)
startSyncingTeamColor(gui)
setObjective(gui)
startSyncingTeamPoints(gui)
disableMouseWhileGuiEnabled(gui)
setupHitmarker(gui)
setupTouchButtonAsync(gui)ブラスターセレクター
ブラスターセレクターは、プレイヤーがラウンドに参加または再参加する前にブラスタータイプを選択するために使用するUIコンポーネントです。サンプルレーザータグゲームは、広い水平スプレッドで複数のビームを生成するブラスターと、単一のビームを生成するブラスターの2種類を提供します。プレイヤーが選択するブラスターのタイプは、ラウンド中の戦略に影響を与えるため、このUIコンポーネントは全体のゲームの重要なワークフローです。
以下の手順では、異なるUI要素グループのためのいくつかのコンテナ、プロンプトを持つヘッダー、ナビゲーションおよび選択ボタン、ブラスターボタンのプレハブを作成する方法を詳述します。全体のコンポーネントのスクリプトロジックは、各ブラスタータイプを表すConfigurationインスタンスに応じて、ブラスターボタンのプレハブに異なる視覚的特性を自動的にポピュレートします。
このセットアップにより、StarterGui.PickABlasterGui内で個別のボタンを作成することなく、ブラスターセレクター内で正しく表示される追加のConfigurationインスタンスを作成できます。

サンプルレーザータグゲーム内でブラスターセレクターを正確に再現するには:
コンポーネント全体のコンテナを作成します。
PickABlaster ScreenGuiオブジェクトにFrameを挿入します。
- エクスプローラーウィンドウで、StarterGuiサービスに移動します。
- 子PickABlasterオブジェクトにカーソルを合わせ、**⊕**アイコンをクリックします。文脈メニューが表示されます。
- 文脈メニューから、Frameを挿入します。

新しいフレームを選択し、プロパティウィンドウで、
- AnchorPointを0.5, 1に設定して、フレームの原点を下部中央に設定します(フレームの左から右に50%、上から下に100%)。
- BackgroundTransparencyを1に設定して、フレームの背景を完全に透明にします。
- Positionを{0.5, 0},{0.9, 0}に設定して、画面の下部中央にフレームを配置します(画面の左から右に50%、上から下に92.4%)。
- Sizeを{0.8, 0},{0.25, 0}に設定して、ブラスターセレクターのUIコンポーネントが画面の大部分を占めてプレイヤーの注意を引くようにします(横に80%、縦に25%)。
- NameをComponentに設定します。

- OPTIONALComponentにUIAspectRatioConstraintを挿入して、フレームとその子UI要素のアスペクト比がプレイヤーの画面サイズに関係なく同じままになるようにします。サンプルでは、UIAspectRatioConstraint.AspectRatioプロパティを5に設定しています。
UI要素グループを保持するためのコンテナを作成します。
ComponentにFrameを挿入します。
新しいフレームを選択し、プロパティウィンドウで、
- AnchorPointを0.5, 0.5に設定して、フレームの原点を中央に設定します(フレームの左から右に50%、上から下に50%)。
- BackgroundTransparencyを1に設定して、フレームの背景を完全に透明にします。
- Positionを{0.5, 0},{0.375, 0}に設定して、コンテナの上部中央にフレームを配置します(親フレームの左から右に50%、上から下に37.5%)。
- Sizeを{1, 0},{0.75, 0}に設定して、選択UIコンポーネントがコンテナの3/4を占めるようにします(親フレームの100%横、75%縦)。
- NameをSelectionFrameに設定します。

ブラスターセレクターのプロンプトを作成します。
SelectionFrameにImageLabelを挿入します。
新しいラベルを選択し、プロパティウィンドウで、
- AnchorPointを0.5, 1に設定して、ラベルの原点を下部中央に設定します(ラベルの左から右に50%、上から下に100%)。
- BackgroundTransparencyを1に設定して、ラベルの背景を完全に透明にします。
- LayoutOrderを-1に設定します。
- Positionを{0.5, 0},{0.22, 0}に設定して、フレームの上部中央にラベルを配置します(親フレームの左から右に50%、上から下に22%)。
- Sizeを{0.45, 0},{0.22, 0}に設定して、プロンプトエリアをフレームのほぼ半分に広げます(親フレームの45%横、22%縦)。
- NameをHeaderに設定します。
- Imageをrbxassetid://14304828123に設定して、台形を表示します。
- ImageTransparencyを0.15に設定して、ヘッダーを半透明にします。

- OPTIONALラベルにUIAspectRatioConstraintを挿入して、ラベルのアスペクト比がプレイヤーの画面サイズに関係なく同じままになるようにします。サンプルでは、UIAspectRatioConstraint.AspectRatioプロパティを13.78に設定しています。
HeaderにTextLabelを挿入して、プロンプトを表示します。
新しいラベルを選択し、プロパティウィンドウで、
- AnchorPointを0.5, 0.5に設定して、新しいラベルの原点を中央に設定します(ラベルの左から右に50%、上から下に50%)。
- BackgroundTransparencyを1に設定して、ラベルの背景を完全に透明にします。
- Positionを{0.5, 0},{0.5, 0}に設定して、ラベルを親ラベルの中央に移動します(親ラベルの左から右に50%、上から下に50%)。
- Sizeを{0.6, 0},{0.55, 0}に設定して、テキストスペースを親ラベルの半分以上に広げます(親ラベルの60%横、55%縦)。
- NameをHeaderTextLabelに設定します。
- FontFaceをMontserratに設定して、未来的な美学に合わせます。
- WeightをMediumに設定して、フォントを太くします。
- Textをブラスターを選択してくださいに設定します。
- TextScaledを有効にします。

ブラスター ボタン コンテナと選択矢印のコンテナを作成します。
SelectionFrame に ImageLabel を挿入します。
新しいラベルを選択し、Properties ウィンドウで、
- デフォルトの Image 値を削除します。
- AnchorPoint を 0.5, 1 に設定して、ラベルの原点を自分の下中央に設定します(ラベルの左から右まで50%、上から下まで100%)。
- BackgroundColor を 0, 0, 0 に設定して、ラベルを黒にします。
- BackgroundTransparency を 0.3 に設定して、ラベルの不透明度を30%減少させ、ゲーム内のすべての黒いUI要素と一致させます。
- Position を {0.5, 0},{1, 0} に設定して、ラベルをフレームの下中央に配置します(親フレームの左から右まで50%、上から下まで100%)。
- Size を {1, 0},{0.77, 0} に設定して、ラベルの領域をプロンプトの下のスペースに広げます(親フレームの100%の横幅と77%の縦幅)。

コンテナの角を丸めます。
- ラベルに UICorner オブジェクトを挿入します。
- 新しいコーナーオブジェクトを選択し、Properties ウィンドウで、CornerRadius を 0.075, 0 に設定して角を丸めます。

ブラスター ボタンのコンテナを作成します。
ステップ 4 のラベルに Frame を挿入します。
新しいフレームを選択し、Properties ウィンドウで、
- AnchorPoint を 0.5, 0.5 に設定して、新しいフレームの原点を自分の中央に設定します(フレームの左から右まで50%、上から下まで50%)。
- BackgroundTransparency を 1 に設定して、フレームの背景を完全に透明にします。
- Position を {0.5, 0},{0.5, 0} に設定して、フレームを親ラベルの中央に配置します(親フレームの左から右まで50%、上から下まで50%)。
- Size を {0.85, 0},{0.77, 0} に設定して、フレームの領域をラベルのほとんどに広げます(親ラベルの85%の横幅と77%の縦幅)。
- Name を Container に設定します。

将来のすべてのブラスター ボタンのためのパディングを作成します。
- ステップ 5 のフレームに UIListLayout オブジェクトを挿入します。
- 新しいレイアウトオブジェクトを選択し、Properties ウィンドウで、
- Padding を 0.035, 0 に設定して、すべての将来のボタンの間にスペースを提供します。
- FillDirection を Horizontal に設定して、各ボタンが隣接して表示されるようにします。
- HorizontalAlignment と VerticalAlignment の両方を Center に設定して、各ボタンが互いに中央に揃うようにします。
左のナビゲーションボタンを作成します。
ステップ 4 の ImageLabel に ImageButton オブジェクトを挿入します。
新しいボタンを選択し、Properties ウィンドウで、
- デフォルトの Image 値を削除します。
- AnchorPoint を 0, 0.5 に設定して、新しいボタンの原点を自分の左中央に設定します(ボタンの左から右まで0%、上から下まで50%)。
- BackgroundTransparency を 0.15 に設定して、ボタンが選択可能であることを示す視覚的フィードバックを提供します。
- Position を {0.02, 0},{0.5, 0} に設定して、親コンテナの左側にボタンのパディングを提供します(親ラベルの左から右まで2%、上から下まで50%)。
- Size を {0.04, 0},{0.33, 0} に設定して、選択ボタンをブラスター ボタンよりもはるかに小さくします(親フレームの4%の横幅と33%の縦幅)。
- Name を NavigationButtonLeft に設定します。

ボタンの角を丸めます。
- ボタンに UICorner オブジェクトを挿入します。
- 新しいコーナーオブジェクトを選択し、Properties ウィンドウで、CornerRadius を 0.1, 0 に設定して角を丸めます。

ボタンに ImageLabel オブジェクトを挿入します。
新しいラベルを選択し、Properties ウィンドウで、
- AnchorPoint を 0.5, 0.5 に設定して、新しいラベルの原点を自分の中央に設定します(ラベルの左から右まで50%、上から下まで50%)。
- Position を {0.45, 0},{0.5, 0} に設定して、ラベルを親ボタンの中央付近に配置します(親ボタンの左から右まで45%、上から下まで50%)。この値は中央ではありません。なぜなら、矢印は {0.5, 0},{0.5, 0} でボタンの中央に見えないからです。
- Size を {0.8, 0},{0.8, 0} に設定して、ラベルの領域をプロンプトの下のスペースに広げます(親フレームの80%の横幅と80%の縦幅)。
- BackgroundTransparency を 1 に設定して、画像の背景を完全に透明にします。
- Image を rbxassetid://14309187238 に設定します。
- ScaleType を Fit に設定します。

右のナビゲーションボタンを作成します。
NavigationButtonLeft を複製します。
複製したボタンを選択し、Properties ウィンドウで、
- AnchorPoint を 1, 0.5 に設定して、新しいボタンの原点を自分の右中央に設定します(ボタンの左から右まで100%、上から下まで50%)。
- Position を {0.98, 0},{0.5, 0} に設定して、親コンテナの右側にボタンのパディングを提供します(親ラベルの左から右まで98%、上から下まで50%)。
- Name を NavigationButtonRight に設定します。
その ImageLabel 子オブジェクトを選択します。
- Rotation を 180 に設定して、画像を反転させます。
- Position を {0.55, 0},{0.5, 0} に設定して、ラベルを親ボタンの中央付近に配置します(親ボタンの左から右まで55%、上から下まで50%)。この値は中央ではありません。なぜなら、矢印は {0.5, 0},{0.5, 0} でボタンの中央に見えないからです。

SELECT ボタンを作成します。
Component に ImageButton を挿入します。このプロセスにより、選択ボタンが SelectionFrame から分離され、コンポーネントのメイン部分と選択ボタンの間にパディングを追加できます。
新しいボタンを選択し、Properties ウィンドウで、
- デフォルトの Image 値を削除します。
- AnchorPoint を 0.5, 1 に設定して、新しいボタンの原点を自分の下中央に設定します(ボタンの左から右まで50%、上から下まで100%)。
- BackgroundTransparency を 0.15 に設定して、ボタンが選択可能であることを示す視覚的フィードバックを提供します。
- Position を {0.5, 0},{0.99, 0} に設定して、ボタンをコンテナの下中央に配置します(親フレームの左から右まで50%、上から下まで99%)。
- Size を {0.17, 0},{0.18, 0} に設定して、ボタンをブラスター ボタンの下に長くします(親フレームの17%の横幅と18%の縦幅)。
- Name を SelectButton に設定します。

ボタンの角を丸めます。
- ボタンに UICorner オブジェクトを挿入します。
- 新しいコーナーオブジェクトを選択し、Properties ウィンドウで、CornerRadius を 0.2, 0 に設定して角を丸めます。

ボタンに TextLabel オブジェクトを挿入して、アクションを表示できるようにします。
新しいラベルを選択し、Properties ウィンドウで、
- AnchorPoint を 0.5, 0.5 に設定して、新しいラベルの原点を自分の中央に設定します(ラベルの左から右まで50%、上から下まで50%)。
- BackgroundTransparency を 1 に設定して、ラベルの背景を完全に透明にします。
- Position を {0.5, 0},{0.5, 0} に設定して、ラベルをボタンの中央に移動します(親ボタンの左から右まで50%、上から下まで50%)。
- Size を {0.9, 0},{0.55, 0} に設定して、テキストスペースを親ラベルのほとんどの幅に広げます(親ラベルの90%の横幅と55%の縦幅)。
- Name を SelectTextLabel に設定します。
- FontFace を Montserrat に設定して、未来的な美学に合わせます。
- Weight を Medium に設定して、フォントを太くします。
- Text を SELECT に設定します。
- TextScaled を有効にします。

ブラスター ボタンのプレハブを作成します。
- ReplicatedStorage サービス内に、UIオブジェクトを整理するためのフォルダ構造を作成します。サンプルでは、Instances フォルダに子として Guis フォルダを使用します。
- Guis フォルダに ImageButton オブジェクトを挿入します。
- 新しいボタンを選択し、Properties ウィンドウで、
- デフォルトの Image 値を削除します。
- AnchorPoint を 0.5, 0.5 に設定して、新しいボタンの原点を自分の中央に設定します(ボタンの左から右まで50%、上から下まで50%)。
- BackgroundTransparency を 0.65 に設定して、ボタンがフォーカスされていないことを示す視覚的フィードバックを提供します。ステップ 12 のスクリプトは、ボタンがフォーカスされているときにプログラム的な視覚的フィードバックを提供します。
- LayoutOrder を 2 に設定します。
- Name を BlasterButtonPrefab に設定します。
- Size を {0.8, 0},{0.8, 0} に設定します。
- ImageTransparency を 1 に設定して、画像を完全に透明にします。
- BlasterButtonPrefab に UIAspectRatioConstraint を挿入して、ボタンのアスペクト比がプレイヤーの画面サイズに関係なく同じになるようにします。
- ボタンの角を丸めます。
- BlasterButtonPrefab に UICorner オブジェクトを挿入します。
- UICorner を選択し、Properties ウィンドウで、CornerRadius を 0.05, 0 に設定して角を丸めます。
- BlasterButtonPrefab に ImageLabel を挿入します。
- 新しいラベルを選択し、Properties ウィンドウで、
- デフォルトの Image 値を削除します。
- AnchorPoint を 0.5, 0.5 に設定して、新しいラベルの原点を自分の中央に設定します(ラベルの左から右まで50%、上から下まで50%)。
- BackgroundTransparency を 1 に設定して、ラベルの背景を完全に透明にします。
- Position を {0.52, 0},{0.497, 0} に設定して、ラベルを親ボタンの中央付近に配置します(親ボタンの左から右まで52%、上から下まで49.7%)。この値は中央ではありません。なぜなら、ブラスターは {0.5, 0},{0.5, 0} でボタンの中央に見えないからです。
- Size を {1.20, 0},{0.9, 0} に設定して、ラベルの領域をボタンの外側に広げます(親ボタンの120%の横幅と90%の縦幅)。
- ScaleType を Fit に設定します。
次の ReplicatedStorage スクリプトをサンプル Laser Tag プレースファイル内で参照し、プログラム的に各ブラスターのボタンを表示し、プレイヤーがフォーカスされていないボタンを選択したときにボタンをスケールし、プレイヤーのブラスター選択をアバターに関連付けます。
次のスクリプトは、ブラスターセレクターを作成するために連携して動作する一連のスクリプトを必要とします。プレイヤーがゲームに参加するか、健康がゼロに達した後にラウンドに再出現すると、このスクリプトはプレイヤーが選択を行うまでブラスターセレクターのすべてのUI要素をアクティブにします。
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local GuiAttribute = require(ReplicatedStorage.GuiAttribute)
local setupBlasterButtons = require(script.setupBlasterButtons)
local connectResetSelectionOnEnabled = require(script.connectResetSelectionOnEnabled)
local localPlayer = Players.LocalPlayer
local gui = localPlayer.PlayerGui:WaitForChild("PickABlasterGui")
setupBlasterButtons(gui)
connectResetSelectionOnEnabled(gui)
gui:SetAttribute(GuiAttribute.selectedIndex, 1)ブラストボタン
ブラストボタンは、プレイヤーがモバイルまたはタブレットデバイスを介してゲームにアクセスしている場合に、ブラスターを発射するために使用する UI コンポーネントです。サンプルのレーザー タグ ゲームでは、テキストなしでボタンの機能を伝えるために、十字線とブラストのアイコンを描いたブラスターボタンを使用しています。

サンプルの Laser Tag ゲーム内でブラストボタンを正確に再作成するには:
HUDGui ScreenGui オブジェクトに ImageButton を挿入します。
Explorer ウィンドウで、StarterGui サービスに移動します。
子の HUDGui オブジェクトにカーソルを合わせ、⊕ アイコンをクリックします。コンテキストメニューが表示されます。
コンテキストメニューから ImageButton を挿入します。

ビューポートで、ボタンをプレイヤーの親指が自然に休む位置に移動し、ボタンがプレイヤーのデバイスでどのように見えるかを視覚的に把握します。その後、Properties ウィンドウで、
- Image を rbxassetid://18308375035 に設定して、ブラストボタンアイコンを表示します。
- PressedImage を rbxassetid://18308372558 に設定して、プレイヤーがボタンを押したときにブラストボタンアイコンの反転バージョンを表示します。
- BackgroundTransparency を 1 に設定して、ラベルの背景を完全に透明にします。
- Name を BlastButton に設定します。
- ScaleType を Fit に設定して、画像がコンテナ内に収まり、さまざまな画面サイズで伸びないようにします。
- ImageTransparency を 0.3 に設定して、ラベルの不透明度を減少させ、ゲーム内のすべての黒いUI要素と一致させます。
BlastButton に UIAspectRatioConstraint を挿入して、ボタンのアスペクト比がプレイヤーの画面サイズに関係なく同じになるようにします。
次の ReplicatedStorage スクリプトをサンプル Laser Tag プレースファイル内で参照し、プレイヤーがタッチ入力を使用しているデバイスでブラストボタンをプログラム的に表示します。
次のスクリプトは、setupTouchButtonAsync を含むメイン ヘッドアップ ディスプレイ (HUD) をセットアップするために連携して動作する一連のモジュール スクリプトを必要とします。プレイヤーがラウンドに参加し、ブラスターを選択すると、このスクリプトはすべての HUD UI 要素がプレイヤーの状態、デバイス、およびチームのステータスに適切に表示されることを保証します。
local Players = game:GetService("Players")
local setPlayerPortrait = require(script.setPlayerPortrait)
local setPlayerName = require(script.setPlayerName)
local startSyncingTeamColor = require(script.startSyncingTeamColor)
local setObjective = require(script.setObjective)
local setupTouchButtonAsync = require(script.setupTouchButtonAsync)
local startSyncingTeamPoints = require(script.startSyncingTeamPoints)
local disableMouseWhileGuiEnabled = require(script.disableMouseWhileGuiEnabled)
local setupHitmarker = require(script.setupHitmarker)
local localPlayer = Players.LocalPlayer
local gui = localPlayer.PlayerGui:WaitForChild("HUDGui")
setPlayerPortrait(gui)
setPlayerName(gui)
startSyncingTeamColor(gui)
setObjective(gui)
startSyncingTeamPoints(gui)
disableMouseWhileGuiEnabled(gui)
setupHitmarker(gui)
setupTouchButtonAsync(gui)プレイヤー UI
Wireframe Your Layouts からの視覚的階層のベスト プラクティスに従って、このセクションでは、プレイヤーの状態に関連するすべての画面上の UI 要素を実装する方法を教えます。これらの UI 要素のグループは画面の側近くに配置されており、プレイヤーはゲームプレイから注意をそらすことなく、この周辺情報を理解できます。

プレイヤーインジケーター
プレイヤーインジケーターは、プレイヤーがチームのスポーンゾーンにスポーンするとすぐに、どのチームに属しているかを迅速に判断するために参照する UI コンポーネントです。サンプルのレーザー タグ ゲームでは、プレイヤーが 緑 チームまたは ピンク チームにいるかどうかに応じて、2 つのバージョンのプレイヤーインジケーターを提供します。


Select a Color Theme からのガイダンスに従って、両方のバージョンのプレイヤーインジケーターは、チームカラーとユニークでシンプルなアイコンを組み合わせており、詳細が最小限に抑えられているため、小さな画面でも読みやすくなっています。視覚的フィードバックの 2 つの形式を提供することは、色盲のプレイヤーにとってデザインをアクセシブルに保つのに役立つため、重要です。

サンプルの Laser Tag ゲーム内でプレイヤーインジケーターコンポーネントを正確に再作成するには:
HUDGui ScreenGui オブジェクトに Frame を挿入します。
- Explorer ウィンドウで、StarterGui サービスに移動します。
- 子の HUDGui オブジェクトにカーソルを合わせ、⊕ アイコンをクリックします。コンテキストメニューが表示されます。
- コンテキストメニューから Frame を挿入します。
新しい Frame を選択し、Properties ウィンドウで、
AnchorPoint を 0, 1 に設定して、フレームの原点を自分の下中央に設定します(フレームの左から右まで0%、上から下まで100%)。
BackgroundTransparency を 1 に設定して、ラベルの背景を完全に透明にします。
Name を PlayerDisplay に設定します。
Position を {0.02, 0},{0.97, 0} に設定して、フレームを画面の左下近くに配置します。
Size を {0.23, 0},{0.08, 0} に設定して、フレームを短くし、広げます。
ClipsDescendants を有効にして、フレームを超えて拡張される子 GuiObjects をトリミングします。

多角形の形状を作成します。
PlayerDisplay に ImageLabel を挿入します。
新しいラベルを選択し、Properties ウィンドウで、
- Image を rbxassetid://14304828123 に設定して、台形アイコンを表示します。
- AnchorPoint を 1, 1 に設定して、ラベルの原点を自分の右下に設定します(ラベルの左から右まで100%、上から下まで100%)。
- BackgroundTransparency を 1 に設定して、ラベルの背景を完全に透明にします。
- Name を Block に設定します。
- Position を {1,0},{1,0} に設定して、ラベルをフレームの右側に配置します。
- Size を {1.858, 0},{0.581, 0} に設定して、ラベルをフレームの外側に広げ、フレームの半分以上の長さに短くします。
- ImageTransparency を 0.15 に設定して、ラベルをわずかに透明にします。
- ScaleType を Fit に設定して、画像がコンテナ内に収まり、さまざまな画面サイズで伸びないようにします。

- Block に UIAspectRatioConstraint を挿入して、ラベルとその子 UI 要素のアスペクト比がプレイヤーの画面サイズに関係なく同じになるようにします。
- 新しい制約を選択し、Properties ウィンドウで、AspectRatio を 13.78 に設定します。
プレイヤーのポートレート用のボックスを作成します。
PlayerDisplay に ImageLabel を挿入します。
新しいラベルを選択し、Properties ウィンドウで、
- Image プロパティ内のプレースホルダー アセット ID を削除します。ステップ 7 のスクリプトがプログラム的にプレイヤーのポートレートを画像ラベルに挿入します。
- AnchorPoint を 0, 1 に設定して、ラベルの原点を自分の左下に設定します(ラベルの左から右まで0%、上から下まで100%)。
- BackgroundColor3 を 0, 0, 0 に設定して、ラベルの背景色を黒に設定します。
- BackgroundTransparency を 0.3 に設定して、ラベルの不透明度を30%減少させ、ゲーム内のすべての黒いUI要素と一致させます。
- Name を PlayerPortrait に設定します。
- Position を {0.11, 0},{1, 0} に設定して、ラベルを多角形の左側に配置します。
- Size を {0.23, 0},{1, 0} に設定して、ラベルを縮小します。
- ImageTransparency を 0.15 に設定して、ラベルをわずかに透明にします。
- ScaleType を Fit に設定して、画像がコンテナ内に収まり、さまざまな画面サイズで伸びないようにします。

- PlayerPortrait に UIAspectRatioConstraint を挿入して、ラベルとその子 UI 要素のアスペクト比がプレイヤーの画面サイズに関係なく同じになるようにします。
- PlayerPortrait に UICorner を挿入し、Properties ウィンドウで、CornerRadius を 0.05, 0 に設定して角をわずかに丸めます。

プレイヤーの名前用のテキストラベルを作成します。
PlayerDisplay に TextLabel オブジェクトを挿入します。
新しいラベルを選択し、Properties ウィンドウで、
- AnchorPoint を 0, 0.5 に設定して、新しいボタンの原点を自分の左中央に設定します(ボタンの左から右まで0%、上から下まで50%)。
- BackgroundTransparency を 1 に設定して、ラベルの背景を完全に透明にします。
- Name を PlayerNameTextLabel に設定します。
- Position を {0.35, 0},{0.72, 0} に設定して、ラベルをコンテナの右側に配置します(親ラベルの左から右まで35%、上から下まで72%)。
- Size を {0.52, 0},{0.3, 0} に設定して、テキストが多角形の形状のほとんどの領域を占めるようにします(親フレームの52%の横幅と30%の縦幅)。
- FontFace を Montserrat に設定して、未来的な美学に合わせます。
- Weight を Bold に設定して、フォントを太くします。
- Text プロパティ内のプレースホルダー テキストを削除します。ステップ 7 のスクリプトがプログラム的にプレイヤーの名前をテキストラベルに挿入します。
- TextScaled を有効にします。
- TextXAlignment を Left に設定します。

プレイヤーのポートレートの左側に表示されるチームアイコンと色を作成します。
PlayerDisplay に Folder を挿入し、名前を TeamIcons に変更します。
緑 チームアイコンと色を作成します。
- TeamIcons に ImageLabel を挿入します。
- 新しいラベルを選択し、Properties ウィンドウで、
- AnchorPoint を 0, 1 に設定して、ラベルの原点を自分の左下に設定します(ラベルの左から右まで0%、上から下まで100%)。
- BackgroundColor3 を 88, 218, 171 に設定して、ラベルの背景色をミントグリーンに設定します。
- Name を TeamAIcon に設定します。
- Position を {0, 0},{1, 0} に設定して、ラベルをフレームの左側に配置します。
- Size を {0.135, 0},{0.58, 0} に設定して、ラベルをプレイヤーのポートレートの左側に縮小します。
- ImageTransparency を 1 に設定して、ラベルを透明にします。

- このラベルが緑チーム用であることを追跡するカスタム属性を構成します。このステップは、ステップ 7 のスクリプトにとって非常に重要です。
- Properties ウィンドウで、Attributes セクションに移動し、プラスアイコンをクリックします。ポップアップダイアログが表示されます。
- Name フィールドに teamColor と入力します。
- Type ドロップダウンメニューで BrickColor を選択します。
- Save ボタンをクリックします。
- 新しい teamColor 属性を Mint に設定します。
- TeamAIcon に UIAspectRatioConstraint を挿入して、ラベルとその子 UI 要素のアスペクト比がプレイヤーの画面サイズに関係なく同じになるようにします。
- アイコンを作成します。
- TeamAIcon に ImageLabel を挿入します。
- 新しいラベルを選択し、Properties ウィンドウで、
- Image を rbxassetid://14309678670 に設定して、緑チームアイコンを表示します。
- AnchorPoint を 0.5, 0.5 に設定して、ラベルの原点を自分の中央に設定します(ラベルの左から右まで50%、上から下まで50%)。
- BackgroundTransparency を 1 に設定して、ラベルの背景を完全に透明にします。
- Name を Icon に設定します。
- Position を {0.5, 0},{0.5, 0} に設定して、ラベルを親ラベルの中央に配置します。
- Size を {0.7, 0},{0.6, 0} に設定して、ラベルを縮小します。
- ScaleType を Fit に設定して、画像がコンテナ内に収まり、さまざまな画面サイズで伸びないようにします。

ピンク チームアイコンと色を作成します。
- TeamAIcon とその子を複製します。
- 複製した TeamAIcon を選択し、Properties ウィンドウで、
- BackgroundColor3 を 255, 170, 255 に設定して、ラベルの背景色をカーネーションピンクに設定します。
- Name を TeamBIcon に設定します。
- teamColor 属性を Carnation Pink に設定します。
- 複製した TeamBIcon の子である Icon を選択し、Properties ウィンドウで Image を rbxassetid://14309678549 に設定して、ピンクチームアイコンを表示します。

次の ReplicatedStorage スクリプトをサンプル Laser Tag プレースファイル内で参照し、プレイヤーがラウンド中にアクティブなときに適切なチームカラーとアイコンでプレイヤーインジケーターをプログラム的に表示します。
次のスクリプトは、startSyncingTeamColor、setPlayerName、および setPlayerPortrait を含む一連のモジュール スクリプトが連携して動作し、プレイヤーがラウンドに参加し、ブラスターを選択した後、すべての HUD UI 要素がプレイヤーの状態、デバイス、およびチームのステータスに適切に表示されることを保証します。
local Players = game:GetService("Players")
local setPlayerPortrait = require(script.setPlayerPortrait)
local setPlayerName = require(script.setPlayerName)
local startSyncingTeamColor = require(script.startSyncingTeamColor)
local setObjective = require(script.setObjective)
local setupTouchButtonAsync = require(script.setupTouchButtonAsync)
local startSyncingTeamPoints = require(script.startSyncingTeamPoints)
local disableMouseWhileGuiEnabled = require(script.disableMouseWhileGuiEnabled)
local setupHitmarker = require(script.setupHitmarker)
local localPlayer = Players.LocalPlayer
local gui = localPlayer.PlayerGui:WaitForChild("HUDGui")
setPlayerPortrait(gui)
setPlayerName(gui)
startSyncingTeamColor(gui)
setObjective(gui)
startSyncingTeamPoints(gui)
disableMouseWhileGuiEnabled(gui)
setupHitmarker(gui)
setupTouchButtonAsync(gui)フォースフィールド画面フォースフィールドスクリーンは、プレイヤーがラウンドに参加または再参加している間、敵チームの攻撃から安全であることを知らせるためにビューポートに重ねられるUI要素です。Choose an Art Styleからのアイコンの美的ガイドラインに従い、サンプルのレーザータグゲームでは、フォースフィールドを象徴するために半透明の六角形パターンを利用しています。このデザインの決定は、ゲーム内のすべてのUIに対する全体的な未来的なアートスタイルを強化するだけでなく、テキストや追加のガイダンスなしでプレイヤーの状態を伝えます。

サンプルのレーザータグゲーム内でフォースフィールドスクリーンを正確に再現するには:
ForceFieldGui ScreenGuiオブジェクトにImageLabelを挿入します。
Explorerウィンドウで、StarterGuiサービスに移動します。
子のForceFieldGuiオブジェクトにカーソルを合わせ、**⊕**アイコンをクリックします。コンテキストメニューが表示されます。
コンテキストメニューからImageLabelを挿入します。

新しいラベルを選択し、Propertiesウィンドウで、
Imageをrbxassetid://14462567888に設定します。
BackgroundTransparencyを0.8に設定してフォースフィールドを半透明にします。
Sizeを{1, 0},{1, 0}に設定して、画像が画面全体を埋めるようにします(親のScreenGuiの100%の横幅と100%の縦幅)。
ScaleTypeをTileに設定して、六角形が画面全体にタイル状に表示されるようにします。
TileSizeを{0, 104},{0, 180}に設定します。

ラベルにUIGradientオブジェクトを挿入します。
新しいグラデーションオブジェクトを選択し、Propertiesウィンドウで、
Colorを青から白に変わり、再び青になるカラシーケンスに設定します。
Colorを120, 192, 250に設定して、すべての六角形に明るい青の色合いを適用します。
Colorプロパティをクリックし、**⋯**ボタンをクリックします。カラシーケンスのポップアップが表示されます。

カラシーケンスの下軸の各三角形は、そのポイントでのプロパティの色値を決定するキーポイントです。
カラシーケンスをクリックしてドラッグし、Time値が0.05に達するまで続け、次にColorの隣の小さな四角をクリックしてColorsポップアップウィンドウを開きます。
明るい白を選択し、ポップアップウィンドウを閉じます。
カラシーケンスをクリックしてドラッグし、Time値が0.95に達するまで続け、再度Colorsポップアップウィンドウを開き、前と同じ白を選択します。

Rotationを225に設定して、カラシーケンスの青い部分が左上と右下の隅に表示されるようにします。

Transparencyを設定して、フォースフィールドがきらめいているように見える数値シーケンスにします。
Transparencyプロパティをクリックし、**⋯**ボタンをクリックします。数値シーケンスのポップアップが表示されます。数値シーケンスの開始と終了の各四角は、そのポイントでのプロパティの透明度値を決定するキーポイントです。
数値シーケンス全体で次の時間と値のプロパティを設定します:
- Time = 0, Value = 0.25
- Time = .101, Value = 0.875
- Time = .183, Value = 0
- Time = .3, Value = 1
- Time = .7, Value = 1
- Time = 1, Value = 0.9


ステップ2からImageLabelを複製します。
複製したラベル内のUIGradientオブジェクトを選択し、Propertiesウィンドウで、
Rotationを-45に設定して、画像を反転させてY軸に沿ってほぼミラーリングします。

きらめきをより自然に見せるためにTransparencyを変更します。
- Transparencyプロパティをクリックし、**⋯**ボタンをクリックします。数値シーケンスのポップアップが表示されます。
- 3番目のキーフレームを選択し、Deleteボタンをクリックします。

サンプルのレーザータグプレースファイル内の次のReplicatedStorageスクリプトを参照して、プレイヤーがラウンドに参加または再参加している間にフォースフィールドスクリーンをプログラム的に表示します。
次のReplicatedStorage.ForceFieldClientVisualsクライアントスクリプトは、デフォルトのForceFieldビジュアルをStarterGui.ForceFieldGuiで置き換えます。プレイヤーがゲームにロードされ、Durationプロパティが0より大きいSpawnLocationでスポーンすると、すべてのゲームでのデフォルトの動作は、アバターに保護された青いオーブを提供し、一時的に健康を失うのを防ぎます。
このスクリプトは、ForceFieldがキャラクターに追加されたときにリスニングを開始し、デフォルトの一人称フォースフィールドビジュアルを無効にし、次にForceFieldGui ScreenGuiオブジェクトを有効にします。これは、プレイヤーが他のプレイヤーがゲームに再出現するのを見ているときの三人称ビジュアルには影響しないことに注意してください。


local Players = game:GetService("Players")
local localPlayer = Players.LocalPlayer
local function onCharacterAddedAsync(character: Model)
local forceField = character:WaitForChild("ForceField", 3)
if not forceField then
-- プレイヤーがフォースフィールドが無効なスポーンポイントでスポーンした場合
return
end
forceField.Visible = false
localPlayer.PlayerGui:WaitForChild("ForceFieldGui").Enabled = true
forceField.Destroying:Wait()
localPlayer.PlayerGui.ForceFieldGui.Enabled = false
end
if localPlayer.Character then
onCharacterAddedAsync(localPlayer.Character)
end
localPlayer.CharacterAdded:Connect(onCharacterAddedAsync)リスポーン画面
リスポーン画面は、プレイヤーがタグ付けされており、サーバーが彼らをスポーンゾーンに戻すプロセスにあることを知らせるためにビューポートを暗くするUI要素です。このUI要素は、プレイヤーがタグ付けされたことを処理し、アクティブなラウンドに再参加する前に次の動きを戦略的に考える時間を与えるために重要です。
サンプルのレーザータグゲームにおけるカスタムリスポーン動作の詳細については、Gameplay ScriptingカリキュラムのRespawn Charactersを参照してください。

サンプルのレーザータグゲーム内でリスポーン画面を正確に再現するには:
中央情報バナーを作成します。
OutStateGui ScreenGuiオブジェクトにImageLabelを挿入します。
Explorerウィンドウで、StarterGuiサービスに移動します。
子のOutStateGuiオブジェクトにカーソルを合わせ、**⊕**アイコンをクリックします。コンテキストメニューが表示されます。
コンテキストメニューからImageLabelを挿入します。

新しいラベルを選択し、Propertiesウィンドウで、
AnchorPointを0.5, 0.5に設定して、新しいボタンの原点をその中央に設定します(ラベルの左から右に50%、上から下に50%)。
BackgroundTransparencyを1に設定して、ラベルの背景を完全に透明にします。
Positionを{0.5, 0},{0.5, 0}に設定して、ラベルをそのコンテナの中央に配置します(親のScreenGuiの左から右に50%、上から下に50%)。
Sizeを{0.48, 0},{0.06, 0}に設定して、ラベルを広げます(親のScreenGuiの横幅の48%と縦幅の6%)。
NameをBlockに設定します。
Imageをrbxassetid://14304827265に設定して、画像を台形にします。
ImageColorを0,0,0に設定して、台形を黒にします。
ImageTransparencyを0.3に設定して、ラベルの不透明度を30%減少させ、ゲーム内のすべての黒いUI要素と一致させます。

BlockにUIAspectRatioConstraintを挿入して、ラベルとその子UI要素のアスペクト比がプレイヤーの画面サイズに関係なく同じままになるようにします。
新しい制約を選択し、PropertiesウィンドウでAspectRatioを13.78に設定します。
Blockに情報テキスト用のTextLabelを挿入します。
新しいラベルを選択し、Propertiesウィンドウで、
AnchorPointを0.5, 0.5に設定して、ラベルの原点をその中央に設定します(ラベルの左から右に50%、上から下に50%)。
BackgroundTransparencyを1に設定して、ラベルの背景を完全に透明にします。
Positionを{0.5, 0},{0.5, 0}に設定して、ラベルをその親ラベルの中央に配置します(親ラベルの左から右に50%、上から下に50%)。
Sizeを{.85, 0},{0.55, 0}に設定して、テキストが台形の面積のほとんどを占めるようにします(親ラベルの横幅の85%と縦幅の55%)。
NameをBodyTextLabelに設定します。
FontFaceをMontserratに設定して、未来的な美学に合わせます。
WeightをBoldに設定して、フォントを太くします。
Textを**Respawning…**に設定します。
TextColor3を255, 255, 255に設定して、テキストを白にします。
TextScaledを有効にします。

ヘッダーを作成します。
BlockにImageLabelを挿入します。
新しいラベルを選択し、Propertiesウィンドウで、
AnchorPointを0.5, 1に設定して、ラベルの原点をその下部中央に設定します(ラベルの左から右に50%、上から下に100%)。
BackgroundTransparencyを1に設定して、ラベルの背景を完全に透明にします。
Positionを{0.5, 0},{0, 0}に設定して、ラベルをその親ラベルの上部中央に配置します(親ラベルの左から右に50%、上から下に0%)。
Sizeを{0.46, 0},{0.56, 0}に設定して、ラベルを広げます(親ラベルの横幅の46%と縦幅の56%)。
NameをHeaderに設定します。
Imageをrbxassetid://14304826985に設定して、画像を多方向にフェードさせます。
ImageColorを245, 46, 46に設定して、フェードを赤にして、プレイヤーがラウンドから一時的に非アクティブであることを示します。

Headerに情報テキスト用のTextLabelを挿入します。
新しいラベルを選択し、Propertiesウィンドウで、
AnchorPointを0.5, 0.5に設定して、ラベルの原点をその中央に設定します(ラベルの左から右に50%、上から下に50%)。
BackgroundTransparencyを1に設定して、ラベルの背景を完全に透明にします。
Positionを{0.5, 0},{0.5, 0}に設定して、ラベルをその親ラベルの中央に配置します(親ラベルの左から右に50%、上から下に50%)。
Sizeを{.85, 0},{0.55, 0}に設定して、テキストがフェードエリアのほとんどを占めるようにします(親ラベルの横幅の85%と縦幅の55%)。
NameをHeaderTextLabelに設定します。
FontFaceをMontserratに設定して、未来的な美学に合わせます。
WeightをBlackに設定して、フォントを太くします。
Textを**TAGGED - YOU'RE OUT!**に設定します。
TextColor3を255, 255, 255に設定して、テキストを白にします。
TextScaledを有効にします。

画面の周囲にフェードを作成します。
- OutStateGuiにImageLabelを挿入します。
- 新しいラベルを選択し、Propertiesウィンドウで、
- AnchorPointを0.5, 0.5に設定して、ラベルの原点をその中央に設定します(ラベルの左から右に50%、上から下に50%)。
- BackgroundColor3を0,0,0に設定して、ラベルの背景色を黒に設定します。
- BackgroundTransparencyを0.5に設定して、ラベルの背景を半透明にします。
- Positionを{0.5, 0},{0.5, 0}に設定して、ラベルをそのコンテナの中央に配置します(親のScreenGuiの左から右に50%、上から下に50%)。
- Sizeを{1, 0},{1, 0}に設定して、ラベルを画面全体に広げます(親のScreenGuiの100%の横幅と100%の縦幅)。
- ZIndexを-1に設定して、他のUI要素の背後にフェードを表示します。
- NameをHeaderに設定します。
- Imageをrbxassetid://14309518613に設定して、画像をボーダーフェードにします。
- ImageTransparencyを0.1に設定して、フェードをわずかに半透明にします。
サンプルのレーザータグプレースファイル内の次のReplicatedStorageスクリプトを参照して、プレイヤーの健康がゼロに達したときにリスポーン画面をプログラム的に表示し、チームのスポーンゾーンに戻るプロセスにあるときに表示します。
次のReplicatedStorage.PlayerStateHandlerクライアントスクリプトには、playerState属性に応じて異なるタイプの動作をトリガーする関数が含まれています。すべてのイベント応答は、このスクリプト内で論理的にグループ化されており、プレイヤーのコントロール、カメラの動き、およびどのUIレイヤーが表示されるかを有効または無効にするために必要です。
プレイヤーの健康がゼロに達すると、playerStateはTaggedOutになり、onTaggedOut()関数がトリガーされます。onTaggedOut()は、次の動作を即座にトリガーします:
- プレイヤーはアリーナ内で移動できません。
- プレイヤーはカメラを動かすことができません。
- プレイヤーはブラスターを使用できません。
- StarterGui.OutStateGuiが独占的に有効になります。
プレイヤーがリスポーンすると、playerStateはSelectingBlasterになり、onSelectingBlaster()関数がトリガーされます。onSelectingBlaster()は、StarterGui.PickABlasterGuiを独占的に有効にし、リスポーン画面を自動的に無効にします。これらの条件の詳細については、Gameplay ScriptingカリキュラムのHandle Client Stateを参照してください。
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local PlayerState = require(ReplicatedStorage.PlayerState)
local PlayerAttribute = require(ReplicatedStorage.PlayerAttribute)
local BlasterState = require(ReplicatedStorage.Blaster.BlasterState)
local togglePlayerMovement = require(script.togglePlayerMovement)
local togglePlayerCamera = require(script.togglePlayerCamera)
local scheduleDestroyForceField = require(ReplicatedStorage.scheduleDestroyForceField)
local localPlayer = Players.LocalPlayer
local playerGui = localPlayer.PlayerGui
local guiLayers = {
playerGui:WaitForChild("HUDGui"),
playerGui:WaitForChild("OutStateGui"),
playerGui:WaitForChild("PickABlasterGui"),
}
-- 指定された例外を除いてすべてのUIレイヤーを無効にします
local function setGuiExclusivelyEnabled(enabledGui: ScreenGui?)
-- guiLayersには、独占的に設定する必要があるguiのリストが含まれています。
for _, screenGui in guiLayers do
screenGui.Enabled = screenGui == enabledGui
end
end
local function onSelectingBlaster()
-- ブラスターを選択している間、プレイヤーが周りを見回せるようにカメラを有効にします
togglePlayerCamera(true)
togglePlayerMovement(false)
setGuiExclusivelyEnabled(playerGui.PickABlasterGui)
-- ブラスターを選択している間はブラスターを無効にします
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Disabled)
end
local function onPlaying()
-- ブラスターを選択した後、プレイヤーの移動を有効にします
togglePlayerMovement(true)
setGuiExclusivelyEnabled(playerGui.HUDGui)
-- プレイ中はブラスターを有効にします
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Ready)
-- プレイヤーがプレイを開始するときにフォースフィールドの破壊ロジックをスケジュールします
scheduleDestroyForceField()
end
local function onTaggedOut()
-- タグ付けされている間はコントロールを無効にします
togglePlayerMovement(false)
togglePlayerCamera(false)
setGuiExclusivelyEnabled(playerGui.OutStateGui)
-- タグ付けされている間はブラスターを無効にします
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Disabled)
end
local function onInLobby()
-- ロビーにいる間はコントロールを有効にします
togglePlayerMovement(true)
togglePlayerCamera(true)
-- ロビーにいる間はすべてのHUDを非表示にします
setGuiExclusivelyEnabled(nil)
-- ロビーにいる間はブラスターを無効にします
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Disabled)
end
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(`無効なプレイヤー状態 ({newPlayerState})`)
end
end
-- 初期プレイヤー状態が設定されている場合はそれを処理します
local initialPlayerState = localPlayer:GetAttribute(PlayerAttribute.playerState)
onPlayerStateChanged(initialPlayerState)
local function updateFromPlayerState()
onPlayerStateChanged(localPlayer:GetAttribute(PlayerAttribute.playerState))
end
-- 将来のプレイヤー状態の更新を処理します
localPlayer:GetAttributeChangedSignal(PlayerAttribute.playerState):Connect(updateFromPlayerState)
-- リスポーン後も変更が適用されるようにします
localPlayer.CharacterAdded:Connect(updateFromPlayerState)SurfaceGuiオブジェクトの作成
3D空間内のパートの表面にUIを表示し、各プレイヤー個別のスクリプトロジックに応じて反応させるには、SurfaceGuiオブジェクトを、UIを表示したいパートに親として設定します。この技術により、UIとそのスクリプトロジックがサーバーと各プレイヤーのクライアントの両方で利用可能になります。
SurfaceGuiオブジェクトには、3D空間内のパートの表面に表示されるすべてのGuiObjectsが含まれています。サンプルのレーザータグゲームには、プレイヤーのブラスターの上に表示されるクールダウンメーターの1つのインスタンスのみが含まれています。このオブジェクトは、各プレイヤーの入力に積極的に反応し、再びブラスターを発射できるときの視覚的フィードバックを提供するため、すべてのプレイヤーにスクリプトロジックが必要です。
SurfaceGuiオブジェクトを作成するには:
- Explorerウィンドウで、ReplicatedStorageサービスにカーソルを合わせ、**⊕**アイコンをクリックします。コンテキストメニューが表示されます。
- コンテキストメニューからPartオブジェクトを挿入します。
- パートにScreenGuiオブジェクトを挿入します。
- 子のUI要素のコンテキストに応じてSurfaceGuiの名前を変更します。
- 3D空間内のパートの表面に表示する必要があるすべてのUI要素について、このプロセスを繰り返します。

クールダウンメーター
クールダウンメーターは、プレイヤーが再びブラスターを発射できるまでの待機時間を知らせるUIコンポーネントです。このわずかな間隔は、プレイヤーがクリックやボタンを押す速度でブラスターを発射できるのを防ぎ、レーザータグのゲームプレイには非現実的です。
サンプルのレーザータグゲーム内でクールダウンメーターを正確に再現するには:
SurfaceGuiオブジェクトを保持するパートを作成します。
- Explorerウィンドウで、Workspaceにカーソルを合わせ、**⊕**アイコンをクリックします。コンテキストメニューが表示されます。
- コンテキストメニューからblockパートを挿入します。これは、プロセスの各ステップで変更を視覚化するための一時的な場所です。
パートをプレイヤーのキャラクターがブラスターを持つ位置の周りに配置し、Propertiesウィンドウで、
Transparencyを1に設定して、パートを完全に透明にします。
NameをCooldownBarPrefabに設定します。
Sizeを0.169, 0.027, 2.537に設定して、パートをブラスターの長さに近いサイズにスケールします。
CanCollideとCanQueryを無効にします。

CooldownBarPrefabにSurfaceGuiを挿入します。
新しいSurfaceGuiを選択し、Propertiesウィンドウで、
FaceをTopに設定して、UIが上向きに表示されるようにします。
LightInfluenceとMaxDistanceを0に設定します。
PixelsPerStudを200に設定します。

黒いバーを作成します。
SurfaceGuiにImageLabelを挿入します。
新しいラベルを選択し、Propertiesウィンドウで、
- デフォルトのImage値を削除します。
- AnchorPointを0.5, 0.5に設定して、ラベルの原点をその中央に設定します(ラベルの左から右に50%、上から下に50%)。
- BackgroundColor3を0,0,0に設定して、ラベルの背景色を黒に設定します。
- BackgroundTransparencyを0.4に設定して、ラベルの背景を半透明にします。
- Positionを{0.5, 0},{0.5, 0}に設定して、ラベルをそのコンテナの中央に配置します(親のSurfaceGuiの左から右に50%、上から下に50%)。
- Sizeを{1, 0},{1, 0}に設定して、ラベルをパート全体に広げます(親のSurfaceGuiの100%の横幅と100%の縦幅)。
- NameをContainerに設定します。

コンテナの角を丸めます。
ContainerにUICornerオブジェクトを挿入します。
UICornerを選択し、PropertiesウィンドウでCornerRadiusを0.15, 0に設定して、角をわずかに丸めます。

赤いバーを作成します。
- ContainerにImageLabelを挿入します。
- 新しいラベルを選択し、Propertiesウィンドウで、
- デフォルトのImage値を削除します。
- AnchorPointを1, 0.5に設定して、ラベルの原点をその右中央に設定します(ラベルの左から右に100%、上から下に50%)。
- BackgroundColor3を172, 13, 13に設定して、ラベルの背景色を暗い赤に設定します。
- BackgroundTransparencyを0.2に設定して、ラベルの背景をわずかに透明にします。
- NameをBarに設定します。
- Positionを{1, 0},{0.5, 0}に設定して、ラベルをその親ラベルの右中央に配置します(親ラベルの左から右に100%、上から下に50%)。
- Sizeを{0, 0},{1, 0}に設定して、ラベルをその親ラベルの上部に長くします(親ラベルの横幅の0%と縦幅の100%)。このステップは、ステップ8のスクリプトで発生するツイーン動作にも有益です。
ラベルの角を丸めます。
- BarにUICornerオブジェクトを挿入します。
- UICornerを選択し、PropertiesウィンドウでCornerRadiusを0.15, 0に設定して、角をわずかに丸めます。
CooldownBarPrefabをReplicatedStorageに移動します。
UIオブジェクトを整理するためのフォルダ構造を作成します。サンプルでは、Instancesフォルダに子のGuisフォルダを使用しています。

CooldownBarPrefabをGuisに移動します。
サンプルのレーザータグプレースファイル内の次のReplicatedStorageスクリプトを参照して、プレイヤーのブラスターにクールダウンメーターをプログラム的に接続し、プレイヤーがブラスターを発射した後に赤いバーをアニメーションさせます。
次のReplicatedStorage.FirstPersonBlasterVisualsクライアントスクリプトは、プレイヤーの一人称ブラスターのすべてのビジュアルロジックを処理します。これは、レーザータグのゲームプレイに対してよりリアルに感じるブラスターのビジュアルを設定するために協力するモジュールスクリプトのセットを必要とします。これには、FirstPersonBlasterVisuals.addCooldownBarとFirstPersonBlasterVisuals.runCooldownBarEffectが含まれます。
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")
local RunService = game:GetService("RunService")
local BlastData = require(ReplicatedStorage.Blaster.BlastData)
local PlayerAttribute = require(ReplicatedStorage.PlayerAttribute)
local PlayerState = require(ReplicatedStorage.PlayerState)
local getBlasterConfig = require(ReplicatedStorage.Blaster.getBlasterConfig)
local runBlastVisuals = require(script.runBlastVisuals)
local setupAnimations = require(script.setupAnimations)
local addCooldownBar = require(script.addCooldownBar)
local runCooldownBarEffect = require(script.runCooldownBarEffect)
local laserBlastedBindableEvent = ReplicatedStorage.Instances.LaserBlastedBindableEvent
local RIG_OFFSET_FROM_CAMERA = CFrame.new(2, -2, -3) * CFrame.Angles(math.rad(0.25), math.rad(95.25), 0)
local localPlayer = Players.LocalPlayer
local currentCamera = Workspace.CurrentCamera
local rigModel = nil
local cooldownBar = nil
local animations = {}
local function addFirstPersonVisuals()
local blasterConfig = getBlasterConfig()
-- 一人称リグを追加
rigModel = blasterConfig.RigModel:Clone()
rigModel.Parent = Workspace
-- クールダウンバーを追加
cooldownBar = addCooldownBar(rigModel.PrimaryPart.CooldownBarAttachment)
animations = setupAnimations(blasterConfig, rigModel)
end
local function removeFirstPersonVisuals()
for _, animation in animations do
animation:Stop()
animation:Destroy()
animation = nil
end
if rigModel then
-- これはリグに親付けされているため、クールダウンバーも破壊します
rigModel:Destroy()
rigModel = nil
end
end
-- ブラスターが発生したときに一人称ビジュアル効果を実行します
laserBlastedBindableEvent.Event:Connect(function(blastData: BlastData.Type)
runBlastVisuals(rigModel.PrimaryPart.TipAttachment, blastData, animations.blastAnimation)
runCooldownBarEffect(cooldownBar)
end)
-- リグをカメラにバインドします(存在する場合)
RunService.RenderStepped:Connect(function()
if rigModel then
-- カメラの位置とRIG_OFFSET_FROM_CAMERAに対してリグのCFrameを更新します
rigModel:PivotTo(currentCamera.CFrame * RIG_OFFSET_FROM_CAMERA)
end
end)
-- プレイ中にブラスタータイプが変更されたときのビジュアルを処理します
localPlayer:GetAttributeChangedSignal(PlayerAttribute.blasterType):Connect(function()
local playerState = localPlayer:GetAttribute(PlayerAttribute.playerState)
if playerState == PlayerState.Playing then
removeFirstPersonVisuals()
addFirstPersonVisuals()
end
end)
-- プレイヤー状態が変更されたときのビジュアルを処理します
localPlayer:GetAttributeChangedSignal(PlayerAttribute.playerState):Connect(function()
local newPlayerState = localPlayer:GetAttribute(PlayerAttribute.playerState)
-- プレイヤーがブラスターを選択しているか、ロビーにいるときはビジュアルを削除します
if newPlayerState == PlayerState.SelectingBlaster or newPlayerState == PlayerState.InLobby then
removeFirstPersonVisuals()
-- プレイヤーがブラスターの選択を終えたときにビジュアルを追加します。
elseif newPlayerState == PlayerState.Playing then
addFirstPersonVisuals()
end
end)BillboardGuiオブジェクトの作成
3D空間内にUI要素を表示し、スクリプトロジックに応じて反応し、各プレイヤーのカメラに常に向くようにするには、BillboardGuiオブジェクトをBasePartまたはAttachmentの子として作成します。これにより、プレイヤー名やマップマーカーなどが表示されます。
サンプルのレーザータグゲームには、ReplicatedStorageサービス内に2つの別々のBillboardGuiオブジェクトが含まれています:
- OtherPlayerIndicatorGuiPrefab - ラウンドでアクティブな各プレイヤーの頭上にピンクまたは緑の円を表示します。
- TaggedOutIndicatorGuiPrefab - プレイヤーがラウンドからタグ付けされているときに、その頭上に表示されます。
BillboardGuiオブジェクトを作成した後、各コンテナの目的に応じてその子のGuiObjectsを作成およびカスタマイズできます。次のセクションでは、サンプルのレーザータグゲーム内で両方のインジケータータイプのUI要素を実装する方法を学びます。プロセスの任意の部分を調整して、独自のゲームの仕様に合わせることができます。
BillboardGuiオブジェクトを作成するには:
- コンテキストメニューからBillboardGuiオブジェクトを挿入します。
- BillboardGuiの名前をその子のUI要素のコンテキストに応じて変更します。
- プレイヤーの頭上に文脈的に表示する必要があるすべてのUI要素について、このプロセスを繰り返します。
チームインジケーター
チームインジケーターは、ラウンド内の他のプレイヤーがどのチームに属しているかをプレイヤーに知らせるUI要素で、味方と敵チームのメンバーを簡単に区別できるようにします。この情報は、ファーストパーソンシューティングゲームのゲームプレイにおいて、プレイヤーが戦闘ゾーンにいる間に迅速な戦略的決定を下す必要があるため、重要です。そうしないと、タグ付けされて試合に負けてしまいます。

サンプルのレーザータグゲーム内でチームインジケーターを正確に再現するには:
一時的なリグにBillboardGuiオブジェクトを挿入します。
ツールバーのHomeまたはAvatarタブからCharacterをクリックします。
利用可能なオプションから選択します。サンプルでは、R15リグタイプ、女性の体形、Rthroアバターを使用しています。リグは3DビューポートとExplorerウィンドウの両方にRigという名前で表示されます。
Explorerウィンドウで、リグの子のHeadメッシュに移動し、**⊕**アイコンをクリックします。コンテキストメニューが表示されます。
コンテキストメニューからBillboardGuiを挿入します。

新しいBillboardGuiを選択し、Propertiesウィンドウで、
LightInfluenceを0に設定して、環境光がインジケーターの色に影響を与えないようにします。
NameをOtherPlayerIndicatorPrefabに設定します。
Sizeを{0, 10},{0, 10}に設定して、ラベルをかなり小さくします。
StudsOffsetWorldSpaceを0, 4, 0に設定して、リグの頭の上に配置します。

OtherPlayerIndicatorPrefabにFrameオブジェクトを挿入します。
新しいフレームを選択し、Propertiesウィンドウで、
AnchorPointを0.5, 0.5に設定して、フレームの原点をその中央に設定します(フレームの左から右に50%、上から下に50%)。
BackgroundColor3を255, 3, 0に設定して、フレームの背景色を赤に設定します(プレースホルダー色)。
Positionを{0.5, 0},{0.5, 0}に設定して、フレームをそのコンテナの中央に配置します(親のBillboardGuiの左から右に50%、上から下に50%)。
Sizeを{1, -2},{1, -2}に設定して、フレームをBillboardGuiの表面積に短くします。

FrameにUICornerオブジェクトを挿入して、角を完全に丸めます。

FrameにUIStrokeオブジェクトを挿入して、インジケーターの円をアウトラインします。

OtherPlayerIndicatorPrefabをReplicatedStorageに移動します。
サンプルのレーザータグ1Aプレースファイル内の次のReplicatedStorageスクリプトを参照して、アクティブなラウンドに参加しているすべてのプレイヤーのためにチームインジケーターをプログラム的に表示します。ただし、敵チームにいる場合や遮蔽されている場合は表示しません。
次のReplicatedStorage.OtherPlayerIndicatorGuiSetupスクリプトは、プレイヤーがアクティブなラウンドにスポーンするときに実行されます。これは、addIndicatorToCharacter()関数を呼び出してチームインジケーターを接続します。この関数は、ラウンドに参加している各プレイヤーキャラクターのHeadオブジェクトを見つけます。すでにチームインジケーターがない場合、スクリプトはotherPlayerIndicatorPrefab UIをクローンしてキャラクターのHeadに追加し、チームインジケーターの色をそのチームの色に設定します。
他のプレイヤーが同じチームにいる場合、チームインジケーターは常に表示されます。オブジェクトが3D空間にある場合、敵チームの他のプレイヤーが遮蔽されている場合のみ、チームインジケーターが表示されます。
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local localPlayer = Players.LocalPlayer
local otherPlayerIndicatorPrefab = ReplicatedStorage.Instances.Guis.OtherPlayerIndicatorPrefab
local characterSpawnConnectionsByPlayer: { [Player]: RBXScriptConnection } = {}
local playerAddedConnection: RBXScriptConnection?
local function removeIndicatorFromPlayer(player: Player)
if not player.Character then
return
end
local head = player.Character:WaitForChild("Head", 3)
if not head then
return
end
local gui = head:FindFirstChild(otherPlayerIndicatorPrefab.Name)
if gui then
gui:Destroy()
end
end
local function addIndicatorToCharacter(otherCharacter: Model?)
local otherPlayer = Players:GetPlayerFromCharacter(otherCharacter)
if not otherPlayer then
return
end
task.spawn(function()
local otherHead = otherCharacter:WaitForChild("Head", 3)
if not otherHead then
return
end
-- ラウンドに参加しているプレイヤーにのみインジケーターを追加します
if not otherPlayer.Team then
return
end
-- 重複したインジケーターを追加しないようにし、存在しない場合にのみ新しいものを作成します
local gui = otherHead:FindFirstChild(otherPlayerIndicatorPrefab.Name)
if not gui then
gui = otherPlayerIndicatorPrefab:Clone()
gui.Frame.BackgroundColor3 = otherPlayer.TeamColor.Color
gui.Parent = otherHead
end
-- インジケーターは、プレイヤーが味方の場合のみ常に上に表示されます
local isFriendly = otherPlayer.Team == localPlayer.Team
gui.AlwaysOnTop = isFriendly
end)
end
local function addIndicatorWhenCharacterSpawns(player: Player)
if characterSpawnConnectionsByPlayer[player] then
return
end
local connection = player.CharacterAdded:Connect(addIndicatorToCharacter)
characterSpawnConnectionsByPlayer[player] = connection
end
local function stopSyncingIndicators()
for _, connection in characterSpawnConnectionsByPlayer do
connection:Disconnect()
end
table.clear(characterSpawnConnectionsByPlayer)
if playerAddedConnection then
playerAddedConnection:Disconnect()
playerAddedConnection = nil
end
for _, player in Players:GetPlayers() do
removeIndicatorFromPlayer(player)
end
end
local function addIndicatorToPlayer(player: Player)
if player == localPlayer then
return
end
addIndicatorToCharacter(player.Character)
addIndicatorWhenCharacterSpawns(player)
end
local function startSyncingIndicators()
for _, player in Players:GetPlayers() do
addIndicatorToPlayer(player)
end
if not playerAddedConnection then
playerAddedConnection = Players.PlayerAdded:Connect(addIndicatorToPlayer)
end
end
local function onLocalTeamChanged()
local localTeam = localPlayer.Team
if localTeam then
startSyncingIndicators()
else
stopSyncingIndicators()
end
end
localPlayer:GetPropertyChangedSignal("Team"):Connect(onLocalTeamChanged)
onLocalTeamChanged()タグ付けインジケーター
タグ付けインジケーターは、他のプレイヤーがラウンドでアクティブでなくなり、スポーンゾーンに戻るプロセスにあることをプレイヤーに知らせるUI要素です。この情報は、ファーストパーソンシューティングゲームのゲームプレイにおいて、プレイヤーが他のプレイヤーをタグ付けした後、すぐに次のターゲットに移動する必要があるため、重要です。そうしないと、同じ場所で長時間プレイすることでアリーナで脆弱になってしまいます。

サンプルのレーザータグゲーム内でタグ付けインジケーターを正確に再現するには:
一時的なリグにBillboardGuiオブジェクトを挿入します。プロセスの各ステップで変更を視覚化できるようにします。
ツールバーのHomeまたはAvatarタブからCharacterをクリックします。
利用可能なオプションから選択します。サンプルでは、R15リグタイプ、男性の体形、Rthroアバターを使用しています。リグは3DビューポートとExplorerウィンドウの両方にRigという名前で表示されます。
Explorerウィンドウで、リグの子のHeadメッシュに移動し、**⊕**アイコンをクリックします。コンテキストメニューが表示されます。
コンテキストメニューからBillboardGuiを挿入します。
1. 新しい BillboardGui を選択し、Properties ウィンドウで、
LightInfluence を 0 に設定して、環境光がインジケーターの色に影響を与えないようにします。
Name を TaggedOutIndicatorGuiPrefab に設定します。
Size を {3, 0},{0.5, 0} に設定して、ラベルのためのスペースを広げます。
StudsOffset を 0, 3.25, 0 に設定して、プレイヤーの頭上に位置させます。

TaggedOutIndicatorGuiPrefab に ImageLabel オブジェクトを挿入します。
新しいラベルを選択し、Properties ウィンドウで、
- AnchorPoint を 0.5, 0.5 に設定して、ラベルの原点をラベルの中央に設定します(ラベルの左から右まで50%、上から下まで50%)。
- BackgroundTransparency を 1 に設定して、ラベルの背景を完全に透明にします。
- Name を Frame に設定します。
- Position を {0.5, 0},{0.5, 0} に設定して、ラベルをそのコンテナの中央に配置します(親の BillboardGui の左から右まで50%、上から下まで50%)。
- Size を {1, 0},{1, 0} に設定して、ラベルを親の BillboardGui 全体に広げます(親の BillboardGui の水平方向100%、垂直方向100%)。
- Image を rbxassetid://14304826985 に設定して、画像を多方向のフェードにします。
- ImageColor を 245, 46, 46 に設定して、ラベルを赤く染めます。

Frame に TextLabel オブジェクトを挿入します。
新しいラベルを選択し、Properties ウィンドウで、
AnchorPoint を 0.5, 0.5 に設定して、ラベルの原点をラベルの中央に設定します(ラベルの左から右まで50%、上から下まで50%)。
BackgroundTransparency を 1 に設定して、ラベルの背景を完全に透明にします。
Name を BodyTextLabel に設定します。
Position を {0.5, 0},{0.5, 0} に設定して、ラベルをそのコンテナの中央に配置します(親のラベルの左から右まで50%、上から下まで50%)。
Size を {0.85, 0},{0.7, 0} に設定して、テキストがフェードエリアのほとんどを占めるようにします(親の画像ラベルの水平方向85%、垂直方向70%)。
FontFace を Montserrat に設定して、未来的な美学に合わせます。
Weight を Bold に設定して、フォントを太くします。
Text を TAGGED に設定します。
TextColor3 を 255, 255, 255 に設定して、テキストを白くします。
TextScaled を有効にします。

TaggedOutIndicatorGuiPrefab を ReplicatedStorage に移動します。
サンプル Laser Tag 1A プレースファイル内の ServerScriptService スクリプトを参照して、プレイヤーがチームのスポーンゾーンにリスポーンしている間にタグ付けされたインジケーターをプログラム的に表示します。
次の ServerScriptService.SetupHumanoid サーバースクリプトは、プレイヤーがゲームをロードするとすぐに実行されます。プレイヤーのキャラクターがデータモデルに追加されるたびに、setupHumanoidAsync がその Humanoid と共に呼び出されることを保証します。
local Players = game:GetService("Players")
local setupHumanoidAsync = require(script.setupHumanoidAsync)
local function onCharacterAdded(player: Player, character: Model)
local humanoid = character:WaitForChild("Humanoid")
setupHumanoidAsync(player, humanoid)
end
local function onPlayerAdded(player: Player)
-- プレイヤーがすでにキャラクターを持っている場合は onCharacterAdded を呼び出す
if player.Character then
onCharacterAdded(player, player.Character)
end
-- このプレイヤーの将来のキャラクタースポーンのために onCharacterAdded を呼び出す
player.CharacterAdded:Connect(function(character: Model)
onCharacterAdded(player, character)
end)
end
-- ゲームにすでにいるプレイヤーに対して onPlayerAdded を呼び出す
for _, player in Players:GetPlayers() do
onPlayerAdded(player)
end
-- 将来のすべてのプレイヤーに対して onPlayerAdded を呼び出す
Players.PlayerAdded:Connect(onPlayerAdded)ユーザーインターフェースデザインカリキュラムの完了おめでとうございます!アートスタイルを作成し、レイアウトをワイヤーフレーム化し、スタジオでデザインを実装する経験を得たので、新しいUIや機能をプロジェクトに拡張するか、サンプルレーザータグゲームの一般的な構成と主要な実装の詳細について学ぶ Gameplay Scripting Curriculum などの追加のチュートリアルカリキュラムに従ってください。楽しい制作を!