インタラクティブUIの作成

*このコンテンツは、ベータ版のAI(人工知能)を使用して翻訳されており、エラーが含まれている可能性があります。このページを英語で表示するには、 こちら をクリックしてください。

ゲーム内のHUD(ヘッドアップディスプレイ)は、一般的にHUDメーターの作成で示されるような、健康メーターなどの非インタラクティブなUI要素を表示します。その上で、ほとんどのゲームには、プレイヤーのアクティベーションに応じて反応するボタンや、アクティベート時にアニメーションするボタン、他のインタラクティブなコントロールと共にメニューをトゥイーンイン/アウトするなどのインタラクティブなUIが必要です。

設定ボタンと音量スライダーを含む設定メニューを表示するゲーム内ビュー。

UIの基本 - HUDメーターを出発点として、UIの基本 - インタラクティビティを完成したリファレンスとして、このチュートリアルでは以下を示します:

  • 画面上部のエッジに設定ボタンを配置する方法。
  • インタラクティブなドラッグ可能なスライダーを含む設定メニューのデザイン。
  • 状態を持つ宣言を使用してUIオブジェクトの拡張可能な制御のための「コントローラー」モジュールを形成するためのModuleScriptsの使用。
  • ボタンをプレイヤーのアクティベーションに接続して設定メニューをトグルイン/アウトする方法。
  • ドラッグ可能なUIスライダーを接続して、効果音とバックグラウンドの雰囲気の音量を別々に調整する方法。

デバイスエミュレーターを有効にする

HUDメーターの作成で述べたように、電話やタブレットは画面スペースが最も少ないため、UI要素が小さな画面に収まり、プレイヤーに明確に表示されることが重要です。まだ行っていない場合は、Studioでデバイスエミュレーターを有効にします:

  1. StudioでUIの基本 - HUDメーターテンプレートを開きます。

  2. Studioのテストメニューから、デバイスエミュレーターをオンにします。

  3. メインビューポートのすぐ上のバーから、iPhone XやSamsung Galaxy A51などの電話エミュレーションを選択します。次に、表示サイズをウィンドウにフィットに設定して、Studioで最大のスペースを利用します。

    ビューポートウィンドウの上部に表示されるデバイスエミュレーター設定オプション。

設定ボタンを作成する

GuiButtonsは、ボタンがクリックまたはタップされたときに発火するマルチプラットフォームのActivatedイベントなどの組み込み機能を持つインタラクティブなユーザーインターフェース要素です。GuiButtonクラスは、TextButtonとImageButtonの2つのバリエーションに拡張され、このチュートリアルでは設定メニューを開閉するために「ギア」形状のImageButtonを使用します。

設定ボタンに使用されるRobloxコンポーネント。

設定ボタンを構築するには:

  1. Explorerウィンドウで、StarterGui内のHUDContainerを見つけます。

    選択されたHUDContainerを表示するExplorerウィンドウ。
  2. HUDContainerにImageButtonを挿入し、名前をSettingsButtonに変更します。

    新しいImageButtonが挿入され、SettingsButtonに名前が変更されたExplorerウィンドウ。 ビューポートに新しいImageButton。
  3. 新しいボタンを選択した状態で、プロパティウィンドウで以下を設定します:

    • AnchorPoint = 0.5, 0.25(水平中央および垂直上四分の一)
    • BackgroundTransparency = 1(完全に透明)
    • Position = 0.5, 0, 0, 0(上部中央の配置)
    • Size = 0.1, 0, 0.1, 0(アスペクト比が制約された場合の画面高さの10%)
    • Image = rbxassetid://104919049969988(「ギア」シンボルのアセットID)
  4. デフォルトプロパティでボタンにUIAspectRatioConstraintを挿入します(幅と高さの比率1:1)。

    SettingsButtonボタンに新しいUIAspectRatioConstraintが挿入されたExplorerウィンドウ。
  5. ボタンの最大ピクセル高さを制限するために、UISizeConstraintを挿入し、そのMaxSizeをinf, 44に設定します。

    SettingsButtonボタンに新しいUISizeConstraintが挿入されたExplorerウィンドウ。
    新しいUISizeConstraintの期待される値を示すプロパティウィンドウ。
    画面の上部中央に配置された最終的な設定ボタン。

設定メニューを作成する

新しい設定ボタンは、設定メニューを開閉するためにスクリプト化され、プレイヤーが必要に応じて設定やその他の情報にアクセスできるようにします。このチュートリアルでは、メニューにはバックグラウンドオーディオと効果音の音量レベルを独立して調整するためのインタラクティブなスライダーが含まれます。

設定メニューに使用される基本コンポーネント。

親フレームを作成する

HUDメーターの作成で述べたように、Frameは他のUIオブジェクトのコンテナとして機能します。設定メニュー全体は、単一の親フレームで構築され、現在の状態に応じて異なる入力に反応する状態を持つオブジェクトとして簡単に管理できます。

  1. HUDContainerにFrameを挿入し、名前をSettingsMenuに変更します。

    新しいフレームが挿入され、SettingsMenuに名前が変更されたExplorerウィンドウ。
  2. SettingsMenuを選択した状態で、以下のプロパティを設定します:

    再配置され、サイズ変更され、透明なネイビーブルーの背景でスタイリングされたフレーム。
  3. SettingsMenuにUIAspectRatioConstraintを挿入し、そのAspectRatioプロパティを2.5に設定します(幅と高さの比率2.5:1)。

    SettingsMenuフレームに新しいUISizeConstraintが挿入されたExplorerウィンドウ。
    新しいUISizeConstraintの期待される値を示すプロパティウィンドウ。
  4. SettingsMenuにUICorner修飾子を挿入し、そのCornerRadiusを0.1, 0に設定します。

    SettingsMenuフレームに新しいUICornerが挿入されたExplorerウィンドウ。
    新しいUICorner修飾子の期待される値を示すプロパティウィンドウ。
  5. SettingsMenuのピクセル幅と高さを制約するために、UISizeConstraintを挿入します。そのMaxSizeを800, infに、MinSizeを350, 0に設定します。

    SettingsMenuフレームに新しいUISizeConstraintが挿入されたExplorerウィンドウ。
    新しいUISizeConstraintの期待される値を示すプロパティウィンドウ。
    丸みを帯びたコーナーでスタイリングされたフレーム。

スライダーを構築する

プレイヤーが音量レベルを調整できるようにするために、設定メニューにはUIDragDetectorによって駆動される2つのドラッグ可能なスライダーウィジェットが含まれます。この便利なオブジェクトは、2Dユーザーインターフェース要素とのインタラクションを促進します。


最初のスライダーの親コンテナを作成するには:

  1. SettingsMenuコンテナに新しいFrameを挿入し、名前をEffectsVolumeSliderに変更します。

    SettingsMenuフレームに新しいフレームが挿入され、EffectsVolumeSliderに名前が変更されたExplorerウィンドウ。
  2. EffectsVolumeSliderフレームを選択した状態で、以下のプロパティを設定します:

    • AnchorPoint = 0.5(中央アンカー)

    • BackgroundTransparency = 1(完全に透明)

    • Position = 0.5, 0, 0.35, 0(水平中央およびコンテナの上から35%)

    • Size = 0.8, 0, 0.1, 0(コンテナの幅の80%および高さの10%)

      スライダー要素を含む空のフレームが挿入された。
  3. EffectsVolumeSliderに新しいUIListLayoutを挿入します。このレイアウト修飾子は、親コンテナ内で兄弟のGuiObjectsを水平方向の行または垂直方向の列に自動的に配置する強力な方法であり、フレックスの概念を適用する能力も含まれています。

    EffectsVolumeSliderフレームに新しいUIListLayoutが挿入されたExplorerウィンドウ。
  4. 新しいUIListLayoutの以下のプロパティを設定します:

スライダーアイコン

オーディオノートと「バースト」シンボルを含むシンプルなアイコンは、プレイヤーが設定メニューを開いたときにスライダーの目的を特定するのに役立ちます。

設定メニュー内のスライダーの目的を示すアイコン。
  1. EffectsVolumeSliderフレームにImageLabelを挿入し、名前をIconに変更します。このアイコンは、プレイヤーがスライダーが制御するゲームの側面を理解するのに役立ちます。

    EffectsVolumeSliderフレームに挿入されたImageLabelを表示するExplorerウィンドウ。
  2. Iconを選択した状態で、以下のプロパティを設定します:

    • BackgroundTransparency = 1(完全に透明)
    • Size = 2.5, 0, 2.5, 0(アスペクト比が制約された場合の親フレームの高さの250%)
    • Image = rbxassetid://90019827067389(オーディオノートと「バースト」シンボルのアセットID)
  3. IconにUIAspectRatioConstraintを挿入し、そのプロパティをデフォルトのままにします(幅と高さの比率1:1)。

    ImageLabelに挿入されたUIAspectRatioConstraintを表示するExplorerウィンドウ。 設定メニュー内の最終的なアイコン。

範囲フレーム

アイコンのすぐ右側には、スライダーのインタラクティブ部分が別のFrame内に含まれている必要があります。

スライダーのインタラクティブ部分のターゲットサイズと位置。
  1. EffectsVolumeSliderフレームに新しいFrameを挿入し、名前をSliderFrameに変更します。これはUIListLayoutの直接の兄弟でなければなりません。

    EffectsVolumeSliderフレームに挿入された子フレームを表示するExplorerウィンドウ。
  2. SliderFrameを選択した状態で、以下のプロパティを設定します:

  3. SliderFrameに以下の修飾子を挿入します:

    アイコンの右側に配置されたスライダーフレーム。

インタラクティブハンドル

スライダーコンテナが構築されたので、プレイヤーがゲームプレイ中にインタラクトできるドラッグ可能なハンドルを作成できます。

範囲フレーム内に配置されたインタラクティブスライダーハンドル。
  1. SliderFrameコンテナに新しいFrameを挿入し、名前をHandleに変更します。

    SliderFrameフレームに挿入された子フレームを表示するExplorerウィンドウ。
  2. Handleを選択した状態で、以下のプロパティを設定します:

    • AnchorPoint = 0.5(中央アンカー)
    • Position = 0.5, 0, 0.5, 0(親フレームの水平および垂直中央)
    • Size = 1.2, 0, 1.2, 0(アスペクト比が制約された場合の親フレームの高さの120%)
    • ZIndex = 3(他のスライダー要素の前に視覚的にレイヤーを配置)
  3. Handleに以下の修飾子を挿入します:

  4. HandleにUIDragDetectorオブジェクトを挿入します。この便利なオブジェクトは、2Dユーザーインターフェース要素とのインタラクションを促進し、奨励します。

    Handleフレームに挿入されたUIDragDetectorを表示するExplorerウィンドウ。
  5. 新しいUIDragDetectorの以下のプロパティを設定します:

  6. ハンドルの線形ドラッグ範囲がそのコンテナに制限されるように、BoundingUIプロパティをSliderFrameコンテナにリンクします:

    1. UIDragDetectorを選択します。
    2. プロパティウィンドウでそのBoundingUIプロパティをクリックします。
    3. Explorerウィンドウに戻り、ハンドルの親SliderFrameをクリックします。
    検出器のBoundingUIプロパティをSliderFrameコンテナにリンクするプロセスを示す図。

    BoundingUIプロパティのリンクは、現在SliderFrameコンテナを反映しています:

    検出器のBoundingUIプロパティがSliderFrameコンテナにリンクされていることを示すプロパティウィンドウ。

今、ゲームをプレイテストすると、ハンドルを親コンテナ内で左右にドラッグできるようになります:

内部フィル

スライダーが0%から100%の範囲を制御することをより明確に示すために、ハンドルの可変位置と同期する内部フィルをコンテナの左側に追加できます。

SliderFrameに挿入された内部フィル部分。
  1. SliderFrameコンテナに新しいFrameを挿入し、名前をInnerFillに変更します。

    SliderFrameフレームに挿入された子フレームを表示するExplorerウィンドウ。
  2. InnerFillフレームの以下のプロパティを設定します:

    • AnchorPoint = 0, 0.5(左端および垂直中央)
    • BackgroundColor3 = [0, 150, 255](スライダーのハンドルに合わせた青)
    • BackgroundTransparency = 0.35(65%不透明)
    • Position = 0, 0, 0.5, 0
    • Size = 0.5, 0, 1, 0(親フレームの幅の50%および高さの100%)
    • ZIndex = 2(親フレームのフィル/アウトラインの前に視覚的にレイヤーを配置)
  3. 親SliderFrameコンテナの「ピル」形状に合わせるために、UICorner修飾子を挿入し、そのCornerRadiusプロパティを0.5, 0に設定します。

    InnerFillフレームに挿入されたUICorner修飾子を表示するExplorerウィンドウ。
    新しいUICornerの期待される値を示すプロパティウィンドウ。
    青い背景と丸みを帯びたコーナーでスタイリングされたInnerFillフレーム。

スライダーを複製する

最初のスライダーが構築されたので、簡単に複製して、別の目的を示すためにいくつかの視覚的な側面を変更できます。この場合、音楽ノートのアイコンで象徴されるバックグラウンドオーディオの音量レベルです。

バックグラウンドオーディオスライダーのターゲット位置。
  1. 完成したEffectsVolumeSliderオブジェクトを選択します。

    選択された完成したEffectsVolumeSliderを表示するExplorerウィンドウ。
  2. 複製します(CtrlDまたは⌘D)し、複製したものの名前をBackgroundVolumeSliderに変更します。

    複製されたスライダーがBackgroundVolumeSliderに名前が変更されたExplorerウィンドウ。
  3. 複製したもののPositionを0.5, 0, 0.7, 0に変更して、最初のスライダーの下に移動します。

    EffectsVolumeSliderの下に配置されたBackgroundVolumeSlider。
  4. BackgroundVolumeSliderの最上位ブランチを展開し、Icon画像ラベルを選択し、そのImageプロパティをrbxassetid://101125859760167(音楽ノートのシンボルのアセットID)に変更します。

    BackgroundVolumeSlider内のIconラベルを表示するExplorerウィンドウ。
    Iconラベルの期待される値を示すプロパティウィンドウ。
    アイコン画像が変更されたBackgroundVolumeSlider。
  5. SliderFrame ⟩ Handleブランチを展開し、その中のUIStroke修飾子を選択し、そのColorプロパティを[255, 0, 125](マゼンタ)に設定します。

    BackgroundVolumeSliderのハンドル内のUIStroke修飾子を表示するExplorerウィンドウ。
    UIStroke修飾子の期待される値を示すプロパティウィンドウ。
    アイコン画像が変更されたBackgroundVolumeSlider。
  6. SliderFrame内のInnerFillフレームを選択し、そのBackgroundColor3プロパティを同じマゼンタ色([255, 0, 125])に変更します。

    BackgroundVolumeSliderのSliderFrameコンテナ内のInnerFillフレームを表示するExplorerウィンドウ。
    InnerFillフレームの期待される値を示すプロパティウィンドウ。
    InnerFillの色が変更されたBackgroundVolumeSlider。

閉じるボタンを作成する

設定メニューの最終要素は、プレイヤーにメニューを閉じるための追加の入力を提供する閉じるボタンです(上部中央のSettingsButtonも同じ目的を果たします)。

右上隅に閉じるボタンが表示された設定メニュー。
  1. SettingsMenuコンテナに新しいImageButtonを挿入し、名前をCloseButtonに変更します。

    SettingsMenuに挿入された新しいImageButtonを表示するExplorerウィンドウ。 設定メニューの左上隅に配置された空のImageButton。
  2. CloseButtonを選択した状態で、以下のプロパティを設定します:

    • AnchorPoint = 1, 0(右上隅)
    • BackgroundTransparency = 1(完全に透明)
    • Position = 1, -10, 0, 10(右上隅から10ピクセルのインセット)
    • Size = 0.15, 0, 0.15, 0(アスペクト比が制約された場合のフレーム高さの15%)
    • Image = rbxassetid://5577404210(閉じるボタンシンボルのアセットID)
    • ImageTransparency = 0.25(75%不透明)
  3. ボタンにデフォルトプロパティでUIAspectRatioConstraintを挿入します(幅と高さの比率1:1)。

    CloseButtonボタンに挿入されたUIAspectRatioConstraintを表示するExplorerウィンドウ。 設定メニューの右上隅に配置された最終的な閉じるボタン。

コントロールモジュールを作成する

拡張可能なコントロールモジュールのセットアップは、各オブジェクト内に配置された個別のスクリプトよりもインタラクティブUI管理をより効率的にします。ModuleScriptsは、クライアント-サーバー境界の異なる側または同じ側のスクリプト間でコードを再利用できるようにすることで、この拡張可能な機能を促進します。

状態を持つオブジェクトコントローラー

以下の状態を持つオブジェクトコントローラーモジュールを使用すると、SettingsButtonやSettingsMenuなどのUIオブジェクトに動作を追加し、さまざまな状態間で簡単にトグル/トゥイーンできます。モジュールを作成するには:

  1. ReplicatedStorageコンテナにModuleScriptを挿入し、名前をStatefulObjectControllerに変更します。

    ReplicatedStorageコンテナ内のStatefulObjectControllerモジュールを表示するExplorerウィンドウ。
  2. モジュール内に以下のコードを貼り付けます:

    StatefulObjectController
    local TweenService = game:GetService("TweenService")
    local StatefulObjectController = {}
    StatefulObjectController.__index = StatefulObjectController
    export type StateName = string
    export type State = {
    transition: TweenInfo,
    properties: { [string]: any },
    }
    function StatefulObjectController.hydrate(props: {
    object: Instance,
    states: { [StateName]: State },
    initialStateName: StateName
    })
    local object, states, initialStateName = props.object, props.states, props.initialStateName
    local self = setmetatable({
    states = states,
    currentStateName = initialStateName,
    tweens = {},
    }, StatefulObjectController)
    -- Create tweens for reuse to avoid making new tweens every time state is changed
    for stateName, state in states do
    self.tweens[stateName] = TweenService:Create(object, state.transition, state.properties)
    end
    self:setState(self.currentStateName)
    return self
    end
    function StatefulObjectController:setState(stateName: StateName)
    local stateTween: Tween = self.tweens[stateName]
    if not stateTween then
    warn(string.format("Attempted to set %s to unknown state '%s'", self.object:GetFullName(), stateName))
    return
    end
    self.currentStateName = stateName
    -- Make sure other tweens aren't conflicting
    for _, tween in self.tweens do
    tween:Cancel()
    end
    stateTween:Play()
    end
    return StatefulObjectController
    行目的
    6‑10このモジュールを使用する際のオートコンプリートとリンティングを改善するために、Luauタイプを定義してエクスポートします。
    12‑33状態を持つUIオブジェクトに動作を初期化して追加するために使用される関数で、GuiObjectをobjectとして、状態とそれぞれのTweenInfoデータのテーブルを受け取り、初期状態名を受け取ります。この関数内で、行26‑28は各状態のTweensを構築し、行30はモジュールのsetState()関数を呼び出してオブジェクトを初期状態に設定します。
    35‑50状態を持つオブジェクトの状態を設定/変更するために使用される関数です。行42はオブジェクトのcurrentStateNameを設定されている状態に設定し、行45‑47は競合を防ぐために実行中のトゥイーンをキャンセルし、行49は状態のトゥイーンを実行します。

スライダーコントローラー

追加のモジュールは、2つの音量スライダーを初期化して制御します。また、各スライダーにコールバック関数を接続して、プレイヤーのスライダーとのインタラクションを検出し、ゲーム内での望ましい変更を適用できるようにします。

  1. ReplicatedStorageコンテナにModuleScriptを挿入し、名前をSliderControllerに変更します。

    ReplicatedStorageコンテナ内のSliderControllerモジュールを表示するExplorerウィンドウ。
  2. モジュール内に以下のコードを貼り付けます:

    SliderController
    local SliderController = {}
    SliderController.__index = SliderController
    export type Value = number
    export type OnChanged = (Value) -> ()
    function SliderController.hydrate(props: {
    object: Instance,
    onChanged: OnChanged,
    initialValue: Value?
    })
    local object, onChanged, initialValue = props.object, props.onChanged, props.initialValue
    local handle = object:FindFirstChild("Handle", true)
    if not handle then
    warn(string.format("Attempted to hydrate slider %s but couldn't find Handle", object:GetFullName()))
    end
    local innerFill = object:FindFirstChild("InnerFill", true)
    if not innerFill then
    warn(string.format("Attempted to hydrate slider %s but couldn't find InnerFill", object:GetFullName()))
    end
    local dragDetector = handle:FindFirstChildWhichIsA("UIDragDetector")
    if not dragDetector then
    warn(string.format("Attempted to hydrate slider %s but couldn't find UIDragDetector", object:GetFullName()))
    end
    local self = setmetatable({
    handle = handle,
    innerFill = innerFill,
    dragDetector = dragDetector,
    value = initialValue or 0.5,
    onChanged = onChanged,
    }, SliderController)
    -- Set initial value
    self:setValue(self.value)
    -- Connect detector to player manipulation
    self.dragConnection = dragDetector.DragContinue:Connect(function()
    self:setValue(handle.Position.X.Scale)
    end)
    return self
    end
    function SliderController:setValue(value: Value)
    local clampedValue = math.clamp(value, 0, 1)
    self.value = clampedValue
    -- Update the handle position and inner frame size to match
    self.handle.Position = UDim2.fromScale(clampedValue, 0.5)
    self.innerFill.Size = UDim2.fromScale(clampedValue, 1)
    -- Run the user's callback with the latest value
    local changeSuccess, changeResult = pcall(self.onChanged, clampedValue)
    if not changeSuccess then
    warn("Error in slider callback:", changeResult)
    end
    end
    return SliderController
    行目的
    7‑46スライダー要素に動作を初期化して追加するために使用される関数で、スライダーの親Frameをobjectとして受け取り、スライダーの変更を処理するためのonChangedコールバック関数と、スライダーのハンドル位置の初期値を受け取ります。この関数内で、行14‑27はスライダーのハンドル、内部フィル、およびUIDragDetector要素が存在することを確認します。行38はモジュールのsetValue()関数を呼び出し、行41‑43はドラッグ検出器のDragContinueイベントをモジュールのsetValue()関数に接続します(次の行の詳細を参照)。
    48‑61スライダーの値を設定するために使用される関数です。この関数内で、行53‑54はハンドルの位置と内部フィルのサイズが同期されることを保証し、行57は変更された値をコールバック関数に渡して、必要に応じて値を利用できるようにします。

設定スクリプトを作成する

設定ボタンと設定メニューが完成したので、コントロールモジュールを利用してすべてを結びつける単一のスクリプトを作成できます。

  1. HUDContainerに新しいLocalScriptを挿入し、その名前をSettingsScriptに変更して目的を説明します。このスクリプトは、管理するトップレベルのUIオブジェクトであるSettingsMenuとSettingsButtonと同じレベル(兄弟)にある必要があります。

    HUDContainerコンテナ内のSettingsScriptスクリプトを表示するExplorerウィンドウ。
  2. スクリプト内に以下のコードを貼り付けます:

    SettingsScript
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local SoundService = game:GetService("SoundService")
    local SliderController = require(ReplicatedStorage.SliderController)
    local StatefulObjectController = require(ReplicatedStorage.StatefulObjectController)
    local HUDContainer = script.Parent
    -- Initialize settings button
    local settingsButton = StatefulObjectController.hydrate({
    object = HUDContainer:FindFirstChild("SettingsButton"),
    states = {
    menuOpen = {
    transition = TweenInfo.new(0.5, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out),
    properties = {
    Rotation = 45,
    },
    },
    menuClosed = {
    transition = TweenInfo.new(0.5, Enum.EasingStyle.Exponential, Enum.EasingDirection.Out),
    properties = {
    Rotation = 0,
    },
    },
    },
    initialStateName = "menuClosed"
    })
    -- Initialize settings menu frame
    local settingsMenu = StatefulObjectController.hydrate({
    object = HUDContainer:FindFirstChild("SettingsMenu"),
    states = {
    menuOpen = {
    transition = TweenInfo.new(0.5, Enum.EasingStyle.Bounce, Enum.EasingDirection.Out),
    properties = {
    Position = UDim2.fromScale(0.5, 0.5),
    Visible = true,
    },
    },
    menuClosed = {
    transition = TweenInfo.new(0),
    properties = {
    Position = UDim2.fromScale(0.5, 0.4),
    Visible = false,
    },
    },
    },
    initialStateName = "menuClosed"
    })
    -- Initialize effects volume slider
    local effectsAudio = SoundService:FindFirstChild("Effects")
    local effectsVolumeSlider = SliderController.hydrate({
    object = HUDContainer:FindFirstChild("EffectsVolumeSlider", true),
    initialValue = effectsAudio and effectsAudio.Volume or 0.5,
    onChanged = function(value: SliderController.Value)
    if effectsAudio then
    effectsAudio.Volume = value
    end
    end,
    })
    -- Initialize background volume slider
    local backgroundAudio = SoundService:FindFirstChild("Background")
    local backgroundVolumeSlider = SliderController.hydrate({
    object = HUDContainer:FindFirstChild("BackgroundVolumeSlider", true),
    initialValue = backgroundAudio and backgroundAudio.Volume or 0.5,
    onChanged = function(value: SliderController.Value)
    if backgroundAudio then
    backgroundAudio.Volume = value
    end
    end,
    })
    -- Connect buttons to player interaction
    HUDContainer:FindFirstChild("SettingsButton").Activated:Connect(function()
    local targetState = if settingsButton.currentStateName == "menuClosed"
    then "menuOpen"
    else "menuClosed"
    settingsButton:setState(targetState)
    settingsMenu:setState(targetState)
    end)
    HUDContainer:FindFirstChild("CloseButton", true).Activated:Connect(function()
    settingsButton:setState("menuClosed")
    settingsMenu:setState("menuClosed")
    end)
  3. スクリプトがコントロールモジュールをどのように利用しているかを探るために、以下のセクションを参照してください。

    行10-27は、設定ボタンに動作を初期化して追加します:

    行目的
    10‑11ローカル参照settingsButtonが宣言され、StatefulObjectController.hydrate()関数で水分補給され、HUDContainer内のSettingsButtonボタンが水分補給するオブジェクトとして参照されます。
    12‑25menuOpenとmenuClosedの2つのユニークな状態を持つstatesテーブルが渡されます。各状態には、特定の状態がpropertiesテーブルで定義されたターゲットプロパティに到達する方法を宣言するためのトランジションが含まれます。この場合、menuOpenはボタンのRotationを45°に変更し、Exponentialトゥイーンで0.5秒かけて変化させ、menuClosedはボタンをデフォルトの回転である0に戻します。
    26ボタンの初期状態がmenuClosedに設定されます(これはstatesテーブル内の任意の状態名に設定できます)。

    スクリプトの下部(行76-86)では、ボタンがプレイヤーのインタラクションに接続されてUIの状態変更をトリガーします:

    行目的
    76‑82SettingsButtonはActivatedイベントに接続され、匿名関数を呼び出します。匿名関数内で、行77‑79はtargetState変数をmenuOpenとmenuClosedの間でトグルします。行80はボタンの状態をtargetStateに設定するためにsetState()を呼び出し、行81はSettingsMenuにも同様に呼び出して、SettingsButtonのアクティベーションに応じて開閉します。
    83‑86CloseButtonはActivatedイベントに接続され、匿名関数を呼び出して、SettingsButtonとSettingsMenuの両方の状態をmenuClosedに設定します。

    行30-49は、設定メニューに動作を初期化して追加します:

    行目的
    30‑31ローカル参照settingsMenuが宣言され、StatefulObjectController.hydrate()関数で水分補給され、HUDContainer内のSettingsMenuフレームが水分補給するオブジェクトとして参照されます。
    32‑46設定ボタンと同様に、menuOpenとmenuClosedの2つのユニークな状態を持つstatesテーブルが渡されます。ここで、menuOpenはフレームのPositionをUDim2.fromScale(0.5, 0.5)に変更し、Bounceトゥイーンで0.5秒かけて変化させ、Visibleの状態をtrueにします。対照的に、menuClosedは位置状態をUDim2.fromScale(0.5, 0.4)に変更し、Visibleをfalseにしますが、行41のTweenInfoが0の期間であるため、状態変更は即座に発生します。
    48フレームの初期状態がmenuClosedに設定されます。

    スクリプトの下部(行76-86)では、設定メニューがプレイヤーのインタラクションにリンクされています:

    行目的
    81SettingsMenuの同じtargetStateを設定して、SettingsButtonのアクティベーションに同期させます。
    85CloseButtonがアクティベートされたときにSettingsMenuの状態をmenuClosedに設定します。

    行51-73は、EffectsVolumeSliderとBackgroundVolumeSliderに動作を初期化して追加します:

    行目的
    52ローカル参照をEffectsのSoundGroupに設定します。SoundGroupを使用すると、複数のSoundsを相互に関連付け、グループのVolumeプロパティを通じてグループ内のすべてのサウンドの音量を制御できます。
    53‑54ローカル参照effectsVolumeSliderが宣言され、SliderController.hydrate()関数でHUDContainer ⟩ SettingsMenu内のEffectsVolumeSliderフレームを水和するオブジェクトとして参照します。trueという2番目のパラメータは、FindFirstChild()メソッドにHUDContainerブランチを再帰的に検索してEffectsVolumeSliderを見つけるよう指示します。
    55スライダーの初期値は、Effectsサウンドグループの現在のVolumeに設定され、フォールバックとして0.5が使用されます。
    56‑60スライダーの値の変更をEffectsサウンドグループの音量に適用するためのコールバック関数を確立します。
    64‑73基本的には行52-61と同じですが、HUDContainer ⟩ SettingsMenu内のBackgroundVolumeSliderフレームを水和し、スライダーの値の変更をBackgroundサウンドグループの音量に適用します。

SettingsScriptが配置されると、ゲームはプレイヤーのインタラクションに関連する一連のUIオブジェクトをリンクする完全に機能するインタラクティブUIの例を提供します。

©2026 Roblox Corporation。Roblox(ロブロックス)、RobloxロゴおよびPowering Imaginationは、米国並びにその他の国における登録商標および非登録商標です。