HUD (Heads-Up Display) w twoim doświadczeniu zwykle wyświetla nieinteraktywne elementy UI, takie jak wskaźnik zdrowia pokazany w Tworzenie wskaźników HUD. Oprócz tego, prawie każde doświadczenie wymaga interaktywnego UI, takiego jak przyciski, które reagują na aktywację przez gracza, animują się po aktywacji, tweenują w/na menu z innymi interaktywnymi kontrolkami itp.

Korzystając z Podstaw UI - Wskaźnik HUD jako miejsca wyjścia i Podstaw UI - Interaktywność jako miejsca odniesienia, ten samouczek demonstruje:
- Jak umieścić przycisk ustawień wzdłuż górnej krawędzi ekranu.
- Projekt menu ustawień zawierającego interaktywne suwakowe elementy do przeciągania.
- Użycie ModuleScripts do tworzenia modułów "kontrolera" dla rozszerzalnej kontroli obiektów UI z deklaracjami stanu.
- Jak połączyć przyciski z aktywacją przez gracza, aby włączać/wyłączać menu ustawień.
- Jak połączyć suwaki UI do przeciągania, aby dostosować głośność efektów dźwiękowych i tła osobno.
Włącz emulator urządzenia
Jak wspomniano w Tworzeniu wskaźników HUD, telefony i tablety mają najmniejszą ilość miejsca na ekranie, więc ważne jest, aby elementy UI pasowały na mniejszych ekranach i były wyraźnie widoczne dla graczy. Jeśli jeszcze tego nie zrobiłeś, włącz Emulator urządzenia w Studio:
Otwórz szablon Podstaw UI - Wskaźnik HUD w Studio.
W menu Test w Studio włącz Emulator urządzenia.
Z paska bezpośrednio nad głównym widokiem wybierz emulację telefonu, taką jak iPhone X lub Samsung Galaxy A51. Następnie ustaw rozmiar widoku na Dopasuj do okna, aby wykorzystać maksymalną przestrzeń w Studio.

Utwórz przycisk ustawień
GuiButtons są interaktywnymi elementami interfejsu użytkownika z wbudowaną funkcjonalnością, taką jak wieloplatformowe wydarzenie Activated, które wywołuje się, gdy przycisk jest klikany lub dotykany. Klasa GuiButton ma dwie odmiany, TextButton i ImageButton, a ten samouczek wykorzystuje "przycisk" w kształcie ImageButton, aby włączyć lub wyłączyć menu ustawień.

Aby skonstruować przycisk ustawień:
W oknie Explorer znajdź HUDContainer w StarterGui.

Z nowym wybranym przyciskiem ustaw następujące w oknie Właściwości:
- AnchorPoint = 0.5, 0.25 (poziomy środek i pionowy górny ćwierć)
- BackgroundTransparency = 1 (w pełni przezroczysty)
- Position = 0.5, 0, 0, 0 (pozycjonowanie w górnym centrum)
- Size = 0.1, 0, 0.1, 0 (10% wysokości ekranu po przymuszeniu proporcji)
- Image = rbxassetid://104919049969988 (identyfikator zasobu symbolu "zębatki")
Wstaw UIAspectRatioConstraint do przycisku z domyślnymi właściwościami (1:1 szerokości do wysokości).

Aby ograniczyć maksymalną wysokość przycisku w pikselach, wstaw UISizeConstraint i ustaw jego MaxSize na inf, 44.



Utwórz menu ustawień
Nowy przycisk ustawień zostanie zaprogramowany, aby włączać i wyłączać menu ustawień, dając graczom dostęp na żądanie do ustawień lub innych informacji. W tym samouczku menu będzie zawierać interaktywne suwaki do dostosowania poziomów głośności dźwięków w tle oraz efektów dźwiękowych niezależnie.

Utwórz rodzicielski ramkę
Jak wspomniano w Tworzeniu wskaźników HUD, Frame służy jako kontener dla innych obiektów UI. Całe menu ustawień zostanie skonstruowane z jednego rodzica, co ułatwi zarządzanie nim jako obiektem stanu, który reaguje na wejście w różny sposób w zależności od bieżącego stanu.
Wstaw nowy Frame do HUDContainer i zmień jego nazwę na SettingsMenu.

Z SettingsMenu zaznaczonym ustaw następujące właściwości:
- AnchorPoint = 0.5 (centrum kotwicy)
- BackgroundColor3 = 30, 30, 60 (granatowy)
- BackgroundTransparency = 0.25 (75% przezroczystości)
- Position = 0.5, 0, 0.5, 0 (środek ekranu)
- Size = 0.75, 0, 0.75, 0 (75% szerokości/wysokości obszaru zagnieżdżonego ekranu)

Wstaw UIAspectRatioConstraint do SettingsMenu i ustaw jego AspectRatio na 2.5. (2.5:1 szerokości do wysokości).


Wstaw modyfikator UICorner do SettingsMenu i ustaw jego CornerRadius na 0.1, 0.


Aby ograniczyć pixelowe szerokość i wysokość SettingsMenu, wstaw UISizeConstraint. Ustaw jego MaxSize na 800, inf oraz MinSize na 350, 0.



Zbuduj suwak
Aby umożliwić graczom dostosowanie poziomów głośności, menu ustawień będzie zawierać dwa przeciągalne widgety suwaków napędzane przez UIDragDetector, wygodny obiekt, który ułatwia interakcję z 2D interfejsu użytkownika.
Aby utworzyć rodzaj kontenera dla pierwszego suwaka:
Wstaw nowy Frame do kontenera SettingsMenu i zmień jego nazwę na EffectsVolumeSlider.

Z ramką EffectsVolumeSlider zaznaczoną, ustaw następujące właściwości:
- AnchorPoint = 0.5 (centrum kotwicy)
- BackgroundTransparency = 1 (w pełni przezroczysty)
- Position = 0.5, 0, 0.35, 0 (poziomy środek i 35% od górnej krawędzi kontenera)
- Size = 0.8, 0, 0.1, 0 (80% szerokości kontenera i 10% jego wysokości)

Wstaw nowy UIListLayout do EffectsVolumeSlider. Ta modyfikator układu jest potężnym sposobem automatycznego układania rodzeństwa GuiObjects w poziome wiersze lub pionowe kolumny w ich rodzicielskim kontenerze, w tym możliwość zastosowania zmienności.

Ustaw następujące właściwości dla nowego UIListLayout:
- Padding = 0.06, 0 (6% odstępu pomiędzy elementami listy)
- FillDirection = Horizontal (układ elementów od lewej do prawej)
- HorizontalFlex = Fill (zmiana rozmiaru elementów w poziomie, aby wypełniały cały rodzicielski kontener, przerywają swój zdefiniowany szerokość)
- VerticalAlignment = Center (wyrównanie elementów wzdłuż ich pionowego środka)
Ikona suwaka
Prosta ikona zawierająca nutę audio i symbol "wybuchu" pomoże graczom zidentyfikować cel suwaka, gdy otworzą menu ustawień.

Wstaw ImageLabel do ramki EffectsVolumeSlider i zmień jej nazwę na Icon. Ta ikona pomoże graczom zrozumieć, który aspekt podczas gry kontroluje suwak.

Z Icon zaznaczoną ustaw następujące właściwości:
- BackgroundTransparency = 1 (w pełni przezroczysty)
- Size = 2.5, 0, 2.5, 0 (250% wysokości ramki nadrzędnej po przymuszeniu proporcji)
- Image = rbxassetid://90019827067389 (identyfikator zasobu nuty audio i symbolu "wybuchu")
Wstaw UIAspectRatioConstraint do Icon i pozostaw jego właściwości jako domyślne (1:1 szerokości do wysokości).


Ramka zakresu
Bezpośrednio po prawej stronie ikony, interaktywna część suwaka powinna być zawarta w innej Frame.

Wstaw nową Frame do ramki EffectsVolumeSlider i zmień jej nazwę na SliderFrame. Zauważ, że musi być bezpośrednim rodzeństwem modyfikatora układu UIListLayout.

Z SliderFrame zaznaczoną ustaw następujące właściwości:
- BackgroundColor3 = 0 (czarny)
- BackgroundTransparency = 0.75 (25% przezroczystości)
- LayoutOrder = 1
- Size = 1, 0, 1, 0 (100% szerokości/wysokości ramki nadrzędnej)
Wstaw następujące modyfikatory do SliderFrame:
- UIStroke z jego Color ustawionym na 0, Thickness na 3, a Transparency na 0.25 (75% przezroczysta czarna obwódka)

Interaktywna rączka
Gdy kontener suwaka został skonstruowany, możesz teraz stworzyć przeciągalną rączkę dla graczy, aby interagować z podczas rozgrywki.

Wstaw nową Frame do kontenera SliderFrame i zmień jej nazwę na Handle.

Z Handle zaznaczoną ustaw następujące właściwości:
- AnchorPoint = 0.5 (centrum kotwicy)
- Position = 0.5, 0, 0.5, 0 (poziomo i pionowo w centrum ramki nadrzędnej)
- Size = 1.2, 0, 1.2, 0 (120% wysokości ramki nadrzędnej po przymuszeniu proporcji)
- ZIndex = 3 (warstwa wizualnie przed innymi elementami suwaka)
Wstaw następujące modyfikatory do Handle:
- UIAspectRatioConstraint z domyślnymi właściwościami (1:1 szerokości do wysokości)
Wstaw obiekt UIDragDetector do Handle. Ten wygodny obiekt ułatwia i zachęca do interakcji z 2D elementami interfejsu użytkownika.

Ustaw następujące właściwości dla nowego UIDragDetector:
- ResponseStyle = Scale (przesuwaj przy użyciu wartości skalowych pozycji rodzica detektora)
Aby upewnić się, że zakres liniowego przeciągania rączki jest ograniczony do jej kontenera, połącz jego właściwość BoundingUI z kontenerem SliderFrame:
- Wybierz UIDragDetector.
- Kliknij właściwość BoundingUI w oknie Właściwości.
- W oknie Explorer kliknij kontener rodzica SliderFrame.

Właściwość BoundingUI teraz odzwierciedla kontener SliderFrame:

Jeśli teraz przeprowadzisz test doświadczenia, będziesz mógł przeciągać rączkę w lewo i w prawo wewnątrz jej kontenera:
Wypełnienie wewnętrzne
Aby bardziej przejrzyście wskazywać, że suwak kontroluje zakres od 0% do 100%, możesz dodać wypełnienie wewnętrzne po lewej stronie kontenera, które będzie synchronizować się z zmienną pozycją rączki.

Wstaw nową Frame do kontenera SliderFrame i zmień jej nazwę na InnerFill.

Ustaw następujące właściwości dla ramki InnerFill:
- AnchorPoint = 0, 0.5 (lewa krawędź i pionowy środek)
- BackgroundColor3 = [0, 150, 255] (niebieski dopasowujący się do rączki suwaka)
- BackgroundTransparency = 0.35 (65% przezroczystości)
- Position = 0, 0, 0.5, 0
- Size = 0.5, 0, 1, 0 (50% szerokości i 100% wysokości ramki nadrzędnej)
- ZIndex = 2 (warstwa wizualnie przed wypełnieniem/obrysem ramki nadrzędnej)
Aby dopasować kształt "pigułki" kontenera nadrzędnego SliderFrame, wstaw modyfikator UICorner i ustaw jego CornerRadius na 0.5, 0.



Duplikacja suwaka
Gdy pierwszy suwak został skonstruowany, możesz go łatwo skopiować i zmodyfikować niektóre aspekty wizualne, aby wskazać inny cel, w tym przypadku poziom głośności audio w tle symbolizowany przez ikonę nut.

Wybierz zakończony obiekt EffectsVolumeSlider.

Duplikuj go (CtrlD lub ⌘D) i zmień nazwę duplikatu na BackgroundVolumeSlider.

Zmienić Position duplikatu na 0.5, 0, 0.7, 0, aby przemieścić go poniżej pierwszego suwaka.

Rozwiń górny poziom gałęzi BackgroundVolumeSlider, wybierz etykietę obrazu Icon i zmień jej Image na rbxassetid://101125859760167 (identyfikator zasobu symbolu z nutami muzycznymi).



Wybierz ramkę InnerFill wewnątrz SliderFrame i zmień jej BackgroundColor3 na ten sam magentowy kolor ([255, 0, 125]).



Utwórz przycisk zamknięcia
Ostatnim elementem menu ustawień jest przycisk zamknięcia, który zapewnia graczom dodatkowy sposób na zamknięcie menu (przycisk SettingsButton w górnym centrum będzie pełnił tę samą funkcję).

Z CloseButton zaznaczoną ustaw następujące właściwości:
- AnchorPoint = 1, 0 (prawy górny róg)
- BackgroundTransparency = 1 (w pełni przezroczysty)
- Position = 1, -10, 0, 10 (10 pikselowy odstęp od górnego prawego rogu)
- Size = 0.15, 0, 0.15, 0 (15% wysokości ramki po wymuszeniu proporcji)
- Image = rbxassetid://5577404210 (identyfikator zasobu symbolu przycisku zamknięcia)
- ImageTransparency = 0.25 (75% przezroczystości)
Wstaw UIAspectRatioConstraint do przycisku z domyślnymi właściwościami (1:1 szerokości do wysokości).


Utwórz moduły kontrolne
Rozszerzalny układ modułu kontrolującego sprawia, że zarządzanie interaktywnym UI jest bardziej usprawnione niż indywidualne skrypty umieszczone w każdym obiekcie. ModuleScripts ułatwia tę funkcjonalność, pozwalając na ponowne wykorzystanie kodu pomiędzy skryptami po obu stronach granicy klienta-serwera lub po tej samej stronie granicy.
Kontroler obiektu ze stanem
Następujący moduł kontrolera obiektu ze stanem pozwala na przypisanie zachowań do obiektów UI, takich jak SettingsButton i SettingsMenu, oraz łatwe przełączanie/tweenowanie między różnymi stanami. Aby stworzyć moduł:

Wklej następujący kod do modułu:
StatefulObjectControllerlocal TweenService = game:GetService("TweenService")local StatefulObjectController = {}StatefulObjectController.__index = StatefulObjectControllerexport type StateName = stringexport 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.initialStateNamelocal self = setmetatable({states = states,currentStateName = initialStateName,tweens = {},}, StatefulObjectController)-- Create tweens for reuse to avoid making new tweens every time state is changedfor stateName, state in states doself.tweens[stateName] = TweenService:Create(object, state.transition, state.properties)endself:setState(self.currentStateName)return selfendfunction StatefulObjectController:setState(stateName: StateName)local stateTween: Tween = self.tweens[stateName]if not stateTween thenwarn(string.format("Attempted to set %s to unknown state '%s'", self.object:GetFullName(), stateName))returnendself.currentStateName = stateName-- Make sure other tweens aren't conflictingfor _, tween in self.tweens dotween:Cancel()endstateTween:Play()endreturn StatefulObjectControllerWyjaśnienie koduLinie Cel 6‑10 Definiuje i eksportuje typy Luau, aby poprawić autouzupełnianie i linting podczas korzystania z tego modułu. 12‑33 Funkcja używana do inicjalizacji i przypisania zachowań do obiektu UI ze stanem, akceptując GuiObject jako object, tabelę stanów i ich odpowiadające dane TweenInfo, oraz nazwę początkowego stanu. Wewnątrz tej funkcji, linie 26‑28 konstruują Tweens dla każdego stanu, a linia 30 wywołuje funkcję modułu setState(), aby ustawić obiektu na początkowym stanie. 35‑50 Funkcja używana do ustawienia/zmiany stanu obiektu ze stanem. Linia 42 ustawia currentStateName obiektu na stan, który jest ustawiany, linie 45‑47 przerywają wszelkie uruchomione tweens, aby uniknąć konfliktów, a linia 49 wykonuje tweens stanu.
Kontroler suwaka
Dodatkowy moduł inicjuje i kontroluje dwa suwaki głośności. Pozwala również połączyć funkcję zwrotną z każdym suwakiem, aby wykrywać interakcję gracza z suwakiem i stosować pożądane zmiany w doświadczeniu.
Wstaw ModuleScript do kontenera ReplicatedStorage i zmień jego nazwę na SliderController.

Wklej następujący kod do modułu:
SliderControllerlocal SliderController = {}SliderController.__index = SliderControllerexport type Value = numberexport type OnChanged = (Value) -> ()function SliderController.hydrate(props: {object: Instance,onChanged: OnChanged,initialValue: Value?})local object, onChanged, initialValue = props.object, props.onChanged, props.initialValuelocal handle = object:FindFirstChild("Handle", true)if not handle thenwarn(string.format("Attempted to hydrate slider %s but couldn't find Handle", object:GetFullName()))endlocal innerFill = object:FindFirstChild("InnerFill", true)if not innerFill thenwarn(string.format("Attempted to hydrate slider %s but couldn't find InnerFill", object:GetFullName()))endlocal dragDetector = handle:FindFirstChildWhichIsA("UIDragDetector")if not dragDetector thenwarn(string.format("Attempted to hydrate slider %s but couldn't find UIDragDetector", object:GetFullName()))endlocal self = setmetatable({handle = handle,innerFill = innerFill,dragDetector = dragDetector,value = initialValue or 0.5,onChanged = onChanged,}, SliderController)-- Set initial valueself:setValue(self.value)-- Connect detector to player manipulationself.dragConnection = dragDetector.DragContinue:Connect(function()self:setValue(handle.Position.X.Scale)end)return selfendfunction SliderController:setValue(value: Value)local clampedValue = math.clamp(value, 0, 1)self.value = clampedValue-- Update the handle position and inner frame size to matchself.handle.Position = UDim2.fromScale(clampedValue, 0.5)self.innerFill.Size = UDim2.fromScale(clampedValue, 1)-- Run the user's callback with the latest valuelocal changeSuccess, changeResult = pcall(self.onChanged, clampedValue)if not changeSuccess thenwarn("Error in slider callback:", changeResult)endendreturn SliderControllerWyjaśnienie koduLinie Cel 7‑46 Funkcja używana do inicjalizacji i przypisywania zachowań do elementu suwaka, akceptując ramkę rodzica suwaka Frame jako object, funkcję zwrotną onChanged do przetwarzania zmian suwaka oraz początkową wartość dla pozycji uchwytu suwaka. Wewnątrz funkcji, linie 14‑27 potwierdzają, że suwak posiada uchwyt, wewnętrzne wypełnienie, i elementy UIDragDetector. Linia 38 wywołuje funkcję modułu setValue(), a linie 41‑43 łączą zdarzenie DragContinue detektora przeciągania z funkcją modułu setValue() (zobacz następny wiersz dla szczegółów). 48‑61 Funkcja używana do ustawienia wartości suwaka. Wewnątrz funkcji, linie 53‑54 zapewniają synchronizację pozycji uchwytu i rozmiaru wewnętrznego wypełnienia, a linia 57 przekazuje zmienną wartość do funkcji zwrotnej, aby można ją wykorzystać według potrzeb.
Utwórz skrypt ustawień
Z przyciskiem ustawień i menu ustawień w pełni, możesz połączyć wszystko w jeden skrypt, który wykorzystuje moduły kontrolne.
Wstaw nowy LocalScript do HUDContainer i zmień jego nazwę na SettingsScript, aby opisać jego cel. Zauważ, że ten skrypt powinien być na tym samym poziomie (rodzeństwo) co SettingsMenu i SettingsButton, obiekty UI najwyższego poziomu, którymi będzie zarządzać.

Wklej następujący kod do skryptu:
SettingsScriptlocal 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 buttonlocal 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 framelocal 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 sliderlocal 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 theneffectsAudio.Volume = valueendend,})-- Initialize background volume sliderlocal 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 thenbackgroundAudio.Volume = valueendend,})-- Connect buttons to player interactionHUDContainer: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)Odnies się do następujących sekcji, aby zbadać, jak skrypt wykorzystuje moduły kontrolne.
Przycisk ustawieńLinie 10-27 inicjalizują i przypisują zachowanie do przycisku ustawień w sposób następujący:
Linie Cel 10‑11 Lokale odniesienie settingsButton jest zadeklarowane i zasymilowane za pomocą funkcji StatefulObjectController.hydrate(), a obiekt SettingsButton w HUDContainer jest odnoszony jako obiekt do zaadoptowania. 12‑25 W tabeli states przekazywane są dwie unikalne stany, menuOpen i menuClosed. Każdy stan zawiera przejście, by zdefiniować (poprzez TweenInfo) jak dany stan osiągnie swoje docelowe właściwości zdefiniowane w tabeli properties. W tym przypadku, menuOpen deklaruje zmianę stanu na 45° dla Rotation przycisku z Exponential tweenem o ½ sekundy, podczas gdy menuClosed skutecznie przywraca przycisk do jego domyślnej rotacji 0. 26 Początkowy stan przycisku jest ustawiony na menuClosed (można to ustawić na jakąkolwiek nazwę stanu w tabeli states). Dalej w skrypcie (linie 76-86), przyciski są podłączone do interakcji gracza, aby wyzwalać zmiany stanu UI:
Linie Cel 76‑82 SettingsButton jest połączony z wydarzeniem Activated z klasy GuiButton, aby wywołać anonimową funkcję. Wewnątrz anonimowej funkcji, linie 77‑79 przełączają zmienną targetState między menuOpen i menuClosed. Linia 80 wywołuje setState(), aby ustawić stan przycisku na targetState, a linia 81 czyni to samo dla SettingsMenu, aby przekaźnik otwierał się lub zamykał przy aktywacji SettingsButton. 83‑86 CloseButton jest połączony z wydarzeniem Activated, aby wywołać anonimową funkcję, która ustawia stan zarówno SettingsButton, jak i SettingsMenu na menuClosed. Menu ustawieńLinie 30-49 inicjalizują i przypisują zachowanie do menu ustawień w sposób następujący:
Linie Cel 30‑31 Lokale odniesienie settingsMenu jest zadeklarowane i zasymilowane za pomocą funkcji StatefulObjectController.hydrate(), a ramka SettingsMenu w HUDContainer jest odnoszona jako obiekt do zaadoptowania. 32‑46 Podobnie jak w przypadku przycisku ustawień, tabela states jest przekazywana z dwoma unikalnymi stanami, menuOpen i menuClosed. Tutaj, menuOpen deklaruje zmianę stanu na UDim2.fromScale(0.5, 0.5) dla Position ramki oraz Bounce tween o ½ sekundy, jak również stan Visible na true. W przeciwieństwie do tego, menuClosed deklaruje zmianę stanu położeniowe na UDim2.fromScale(0.5, 0.4) oraz Visible na false, ale TweenInfo z 0 czasem na linii 41 sprawia, że zmiana stanu zachodzi natychmiast. 48 Początkowy stan ramki jest ustawiony na menuClosed. Dalsze w skrypcie (linie 76-86), menu ustawień jest powiązane z interakcją gracza:
Linie Cel 81 Ustawia ten sam targetState dla SettingsMenu, aby zsynchronizować z aktywacją SettingsButton. 85 Ustawia stan SettingsMenu na menuClosed, gdy CloseButton jest aktywowany. Suwaki głośnościLinie 51-73 inicjalizują i przypisują zachowanie do EffectsVolumeSlider i BackgroundVolumeSlider w sposób następujący:
Linie Cel 52 Ustawia lokalne odniesienie do Efektów SoundGroup w SoundService. SoundGroup pozwala na powiązanie wielu Sounds i kontrolowanie głośności każdego dźwięku w grupie za pomocą właściwości Volume grupy. 53‑54 Lokalne odniesienie effectsVolumeSlider jest zadeklarowane i zainicjowane za pomocą funkcji SliderController.hydrate(), a ramka EffectsVolumeSlider w HUDContainer ⟩ SettingsMenu jest odniesiona jako obiekt do nawadniania. Zauważ, że drugi parametr true dla FindFirstChild() nakazuje metodzie przeszukiwanie rekurencyjnie gałęzi HUDContainer, aby znaleźć EffectsVolumeSlider. 55 Początkowa wartość suwaka jest ustawiana na bieżącą Volume grupy dźwięków Efektów, lub 0.5 jako wartość zapasowa. 56‑60 Ustanawia funkcję zwrotną, aby zastosować zmiany wartości suwaka do głośności grupy dźwięków Efektów. 64‑73 W zasadzie to samo co linie 52-61, z tym że nawadnia ramkę BackgroundVolumeSlider w HUDContainer ⟩ SettingsMenu i stosuje zmiany wartości suwaka do głośności grupy dźwięków Background.
Z SettingsScript w miejscu, doświadczenie teraz oferuje w pełni operujący interaktywny przykład UI, który łączy pokrewne zestawy obiektów UI z interakcją gracza.






