Samouczki dla średnio zaawansowanych

Twórz interaktywne UI

*Ta zawartość została przetłumaczona przy użyciu narzędzi AI (w wersji beta) i może zawierać błędy. Aby wyświetlić tę stronę w języku angielskim, kliknij tutaj.

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.

Widok w grze umożliwiający dostęp do ustawień i menu ustawień z suwakami głośności.

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:

  1. Otwórz szablon Podstaw UI - Wskaźnik HUD w Studio.

  2. W menu Test w Studio włącz Emulator urządzenia.

  3. 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.

    Opcje ustawień emulatora urządzenia wskazane u góry okna widoku.

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ń.

Komponent Roblox użyty do przycisku ustawień.

Aby skonstruować przycisk ustawień:

  1. W oknie Explorer znajdź HUDContainer w StarterGui.

    Okno eksploratora pokazujące zaznaczony HUDContainer.
  2. Wstaw ImageButton do HUDContainer i zmień jego nazwę na SettingsButton.

    Okno eksploratora pokazujące nowy przycisk ImageButton wstawiony i przemianowany na SettingsButton. Nowy ImageButton w widoku.
  3. 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")
  4. Wstaw UIAspectRatioConstraint do przycisku z domyślnymi właściwościami (1:1 szerokości do wysokości).

    Okno eksploratora pokazujące nowy UIAspectRatioConstraint wstawiony do przycisku SettingsButton.
  5. Aby ograniczyć maksymalną wysokość przycisku w pikselach, wstaw UISizeConstraint i ustaw jego MaxSize na inf, 44.

    Okno eksploratora pokazujące nowy UISizeConstraint wstawiony do przycisku SettingsButton.
    Okno właściwości pokazujące oczekiwane wartości dla nowego UISizeConstraint.
    Ostateczny przycisk ustawień w górnym centrum ekranu.

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.

Podstawowe komponenty użyte do menu ustawień.

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.

  1. Wstaw nowy Frame do HUDContainer i zmień jego nazwę na SettingsMenu.

    Okno eksploratora pokazujące nową ramkę wstawioną i przemianowaną na SettingsMenu.
  2. Z SettingsMenu zaznaczonym ustaw następujące właściwości:

    Ramka przeniesiona, zmieniona rozmiarów i stylizowana z przezroczystym granatowym tłem.
  3. Wstaw UIAspectRatioConstraint do SettingsMenu i ustaw jego AspectRatio na 2.5. (2.5:1 szerokości do wysokości).

    Okno eksploratora pokazujące nowy UISizeConstraint wstawiony do ramki SettingsMenu.
    Okno właściwości pokazujące oczekiwane wartości dla nowego UISizeConstraint.
  4. Wstaw modyfikator UICorner do SettingsMenu i ustaw jego CornerRadius na 0.1, 0.

    Okno eksploratora pokazujące nowy UICorner wstawiony do ramki SettingsMenu.
    Okno właściwości pokazujące oczekiwane wartości dla nowego modyfikatora UICorner.
  5. Aby ograniczyć pixelowe szerokość i wysokość SettingsMenu, wstaw UISizeConstraint. Ustaw jego MaxSize na 800, inf oraz MinSize na 350, 0.

    Okno eksploratora pokazujące nowy UISizeConstraint wstawiony do ramki SettingsMenu.
    Okno właściwości pokazujące oczekiwane wartości dla nowego UISizeConstraint.
    Ramka stylizowana z zaokrąglonymi rogami.

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:

  1. Wstaw nowy Frame do kontenera SettingsMenu i zmień jego nazwę na EffectsVolumeSlider.

    Okno eksploratora pokazujące nową ramkę wstawioną do ramki SettingsMenu, przemianowaną na EffectsVolumeSlider.
  2. 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)
    Pusta ramka wstawiona w celu pomieszczenia elementów suwaka.
  3. 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.

    Okno eksploratora pokazujące nowy UIListLayout wstawiony do ramki EffectsVolumeSlider.
  4. 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ń.

Ikona wskazująca cel suwaka w menu ustawień.
  1. Wstaw ImageLabel do ramki EffectsVolumeSlider i zmień jej nazwę na Icon. Ta ikona pomoże graczom zrozumieć, który aspekt podczas gry kontroluje suwak.

    Okno eksploratora pokazujące wstawioną ImageLabel do ramki EffectsVolumeSlider.
  2. 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")
  3. Wstaw UIAspectRatioConstraint do Icon i pozostaw jego właściwości jako domyślne (1:1 szerokości do wysokości).

    Okno eksploratora pokazujące UIAspectRatioConstraint wstawiony do ImageLabel. Zakończona ikona w menu ustawień.

Ramka zakresu

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

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

    Okno eksploratora pokazujące ramkę dziecko wstawioną do ramki EffectsVolumeSlider.
  2. Z SliderFrame zaznaczoną ustaw następujące właściwości:

  3. Wstaw następujące modyfikatory do SliderFrame:

    Ramka suwaka umiejscowiona po prawej stronie ikony.

Interaktywna rączka

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

Interaktywna rączka suwaka umiejscowiona w ramce zakresu.
  1. Wstaw nową Frame do kontenera SliderFrame i zmień jej nazwę na Handle.

    Okno eksploratora pokazujące ramkę dziecko wstawioną do ramki SliderFrame i przemianowaną na Handle.
  2. 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)
  3. Wstaw następujące modyfikatory do Handle:

  4. Wstaw obiekt UIDragDetector do Handle. Ten wygodny obiekt ułatwia i zachęca do interakcji z 2D elementami interfejsu użytkownika.

    Okno eksploratora pokazujące UIDragDetector wstawiony do ramki Handle.
  5. Ustaw następujące właściwości dla nowego UIDragDetector:

  6. 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:

    1. Kliknij właściwość BoundingUI w oknie Właściwości.
    2. W oknie Explorer kliknij kontener rodzica SliderFrame.
    Diagram ilustrujący proces łączenia właściwości BoundingUI detektora z kontenerem SliderFrame.

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

    Okno właściwości pokazujące połączoną właściwość BoundingUI detektora z kontenerem 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.

Część wypełnienia wewnętrznego suwaka wstawiona do SliderFrame.
  1. Wstaw nową Frame do kontenera SliderFrame i zmień jej nazwę na InnerFill.

    Okno eksploratora pokazujące ramkę dziecko wstawioną do ramki SliderFrame i przemianowaną na InnerFill.
  2. 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)
  3. Aby dopasować kształt "pigułki" kontenera nadrzędnego SliderFrame, wstaw modyfikator UICorner i ustaw jego CornerRadius na 0.5, 0.

    Okno eksploratora pokazujące modyfikator UICorner wstawiony do ramki InnerFill.
    Okno właściwości pokazujące oczekiwane wartości dla nowego UICorner.
    Ramka InnerFill stylizowana z niebieskim tłem i zaokrąglonymi rogami.

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.

Docelowa pozycja suwaka dla głośności tła.
  1. Wybierz zakończony obiekt EffectsVolumeSlider.

    Okno eksploratora pokazujące zaznaczony zakończony EffectsVolumeSlider.
  2. Duplikuj go (CtrlD lub D) i zmień nazwę duplikatu na BackgroundVolumeSlider.

    Okno eksploratora pokazujące duplikowany suwak przemianowany na BackgroundVolumeSlider.
  3. Zmienić Position duplikatu na 0.5, 0, 0.7, 0, aby przemieścić go poniżej pierwszego suwaka.

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

    Okno eksploratora pokazujące etykietę Icon wewnątrz BackgroundVolumeSlider.
    Okno właściwości pokazujące oczekiwane wartości dla etykiety Icon.
    BackgroundVolumeSlider ze zmodyfikowanym obrazem ikony.
  5. Rozwiń gałąź SliderFrameHandle, wybierz modyfikator UIStroke w jej wnętrzu i ustaw jego Color na [255, 0, 125] (magenta).

    Okno eksploratora pokazujące modyfikator UIStroke wewnątrz uchwytu BackgroundVolumeSlider.
    Okno właściwości pokazujące oczekiwane wartości dla modyfikatora UIStroke.
    BackgroundVolumeSlider z zmodyfikowanym obrazem ikony.
  6. Wybierz ramkę InnerFill wewnątrz SliderFrame i zmień jej BackgroundColor3 na ten sam magentowy kolor ([255, 0, 125]).

    Okno eksploratora pokazujące ramkę InnerFill wewnątrz kontenera SliderFrame BackgroundVolumeSlider.
    Okno właściwości pokazujące oczekiwane wartości dla ramki InnerFill.
    BackgroundVolumeSlider ze zmodyfikowanym kolorem InnerFill.

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ę).

Menu ustawień z przyciskiem zamknięcia wskazanym w prawym górnym rogu.
  1. Wstaw nowy ImageButton do kontenera SettingsMenu i zmień jego nazwę na CloseButton.

    Okno eksploratora pokazujące nowy przycisk ImageButton wstawiony do SettingsMenu i przemianowany na CloseButton. Pusty ImageButton umiejscowiony w lewym górnym rogu menu ustawień.
  2. 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)
  3. Wstaw UIAspectRatioConstraint do przycisku z domyślnymi właściwościami (1:1 szerokości do wysokości).

    Okno eksploratora pokazujące UIAspectRatioConstraint wstawiony do przycisku CloseButton. Zakończony przycisk zamknięcia w prawym górnym rogu menu ustawień.

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ł:

  1. Wstaw ModuleScript do kontenera ReplicatedStorage i zmień jego nazwę na StatefulObjectController.
Okno eksploratora pokazujące moduł StatefulObjectController wewnątrz kontenera ReplicatedStorage.
  1. Wklej następujący kod do modułu:

    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
    LinieCel
    610Definiuje i eksportuje typy Luau, aby poprawić autouzupełnianie i linting podczas korzystania z tego modułu.
    1233Funkcja 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 2628 konstruują Tweens dla każdego stanu, a linia 30 wywołuje funkcję modułu setState(), aby ustawić obiektu na początkowym stanie.
    3550Funkcja używana do ustawienia/zmiany stanu obiektu ze stanem. Linia 42 ustawia currentStateName obiektu na stan, który jest ustawiany, linie 4547 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.

  1. Wstaw ModuleScript do kontenera ReplicatedStorage i zmień jego nazwę na SliderController.

    Okno eksploratora pokazujące moduł SliderController wewnątrz kontenera ReplicatedStorage.
  2. Wklej następujący kod do modułu:

    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
    LinieCel
    746Funkcja 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 1427 potwierdzają, że suwak posiada uchwyt, wewnętrzne wypełnienie, i elementy UIDragDetector. Linia 38 wywołuje funkcję modułu setValue(), a linie 4143 łączą zdarzenie DragContinue detektora przeciągania z funkcją modułu setValue() (zobacz następny wiersz dla szczegółów).
    4861Funkcja używana do ustawienia wartości suwaka. Wewnątrz funkcji, linie 5354 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.

  1. 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ć.

    Okno eksploratora pokazujące skrypt SettingsScript wewnątrz kontenera HUDContainer.
  2. Wklej następujący kod do skryptu:

    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. Odnies się do następujących sekcji, aby zbadać, jak skrypt wykorzystuje moduły kontrolne.

    Linie 10-27 inicjalizują i przypisują zachowanie do przycisku ustawień w sposób następujący:

    LinieCel
    1011Lokale odniesienie settingsButton jest zadeklarowane i zasymilowane za pomocą funkcji StatefulObjectController.hydrate(), a obiekt SettingsButton w HUDContainer jest odnoszony jako obiekt do zaadoptowania.
    1225W 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.
    26Począ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:

    LinieCel
    7682SettingsButton jest połączony z wydarzeniem Activated z klasy GuiButton, aby wywołać anonimową funkcję. Wewnątrz anonimowej funkcji, linie 7779 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.
    8386CloseButton jest połączony z wydarzeniem Activated, aby wywołać anonimową funkcję, która ustawia stan zarówno SettingsButton, jak i SettingsMenu na menuClosed.

    Linie 30-49 inicjalizują i przypisują zachowanie do menu ustawień w sposób następujący:

    LinieCel
    3031Lokale odniesienie settingsMenu jest zadeklarowane i zasymilowane za pomocą funkcji StatefulObjectController.hydrate(), a ramka SettingsMenu w HUDContainer jest odnoszona jako obiekt do zaadoptowania.
    3246Podobnie 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.
    48Początkowy stan ramki jest ustawiony na menuClosed.

    Dalsze w skrypcie (linie 76-86), menu ustawień jest powiązane z interakcją gracza:

    LinieCel
    81Ustawia ten sam targetState dla SettingsMenu, aby zsynchronizować z aktywacją SettingsButton.
    85Ustawia stan SettingsMenu na menuClosed, gdy CloseButton jest aktywowany.

    Linie 51-73 inicjalizują i przypisują zachowanie do EffectsVolumeSlider i BackgroundVolumeSlider w sposób następujący:

    LinieCel
    52Ustawia 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.
    5354Lokalne 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.
    55Początkowa wartość suwaka jest ustawiana na bieżącą Volume grupy dźwięków Efektów, lub 0.5 jako wartość zapasowa.
    5660Ustanawia funkcję zwrotną, aby zastosować zmiany wartości suwaka do głośności grupy dźwięków Efektów.
    6473W 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.

©2026 Roblox Corporation. Nazwa Roblox, logo Roblox oraz hasło „Powering Imagination” należą do naszych zarejestrowanych i niezarejestrowanych znaków towarowych na terenie Stanów Zjednoczonych oraz w innych krajach.