Tutoriais intermediários

Crie uma UI interativa

*Este conteúdo é traduzido por IA (Beta) e pode conter erros. Para ver a página em inglês, clique aqui.

Um HUD (Heads-Up Display) em sua experiência comumente exibe elementos de UI não interativos, como o medidor de saúde demonstrado em Criar medidores HUD. Além disso, quase toda experiência requer UI interativa, como botões que respondem à ativação do jogador, que animam quando ativados, que fazem menus aparecerem/desaparecerem com outros controles interativos, etc.

Visão do jogo mostrando um botão de configurações e um menu de configurações com controles deslizantes de volume.

Usando Fundamentos de UI - Medidor HUD como um ponto de partida e Fundamentos de UI - Interatividade como um lugar de referência finalizado, este tutorial demonstra:

  • Como posicionar um botão de configurações ao longo da borda superior da tela.
  • Design de um menu de configurações contendo controles deslizantes interativos arrastáveis.
  • Uso de um ModuleScripts para formar módulos "controladores" para controle extensível de objetos de UI com declarações de estado.
  • Como conectar botões à ativação do jogador para alternar a abertura e fechamento do menu de configurações.
  • Como conectar controles deslizantes de UI arrastáveis para ajustar o volume de efeitos sonoros e do ambiente de fundo separadamente.

Habilitar o Emulador de Dispositivo

Como mencionado em Criar medidores HUD, telefones e tablets têm a menor quantidade de espaço de tela, portanto, é importante que seus elementos de UI se encaixem em telas menores e que sejam claramente visíveis para os jogadores. Se você ainda não fez isso, habilite o Emulador de Dispositivo no Studio:

  1. Abra o template Fundamentos de UI - Medidor HUD no Studio.

  2. No menu Testar do Studio, ative o Emulador de Dispositivo.

  3. Na barra logo acima da janela principal, selecione uma emulação de telefone como iPhone X ou Samsung Galaxy A51. Em seguida, defina o tamanho da visualização como Ajustar à Janela para utilizar ao máximo o espaço no Studio.

    Configurações do Emulador de Dispositivo indicadas na parte superior da janela de visualização.

Criar o botão de configurações

GuiButtons são elementos interativos da interface do usuário com funcionalidade embutida, como o evento multiplataforma Activated, que é acionado quando o botão é clicado ou pressionado. A classe GuiButton se estende a duas variações, TextButton e ImageButton, e este tutorial utiliza um ImageButton com formato de "engrenagem" para alternar o menu de configurações aberto ou fechado.

Componente Roblox usado para o botão de configurações.

Para construir o botão de configurações:

  1. Na janela Explorer, localize HUDContainer dentro de StarterGui.

    Janela Explorer mostrando o HUDContainer selecionado.
  2. Insira um ImageButton dentro de HUDContainer e renomeie-o para SettingsButton.

    Janela Explorer mostrando o novo ImageButton inserido e renomeado para SettingsButton. Novo ImageButton na visualização.
  3. Com o novo botão selecionado, defina o seguinte na janela Propriedades:

    • AnchorPoint = 0.5, 0.25 (centro horizontal e um quarto superior verticalmente)
    • BackgroundTransparency = 1 (totalmente transparente)
    • Position = 0.5, 0, 0, 0 (posicionamento no centro superior)
    • Size = 0.1, 0, 0.1, 0 (10% da altura da tela uma vez que a proporção é restringida)
    • Image = rbxassetid://104919049969988 (ID do ativo do símbolo "engrenagem")
  4. Insira um UIAspectRatioConstraint no botão com propriedades padrão (proporção 1:1 de largura para altura).

    Janela Explorer mostrando um novo UIAspectRatioConstraint inserido no botão SettingsButton.
  5. Para limitar a altura máxima em pixels do botão, insira um UISizeConstraint e defina seu MaxSize para inf, 44.

    Janela Explorer mostrando um novo UISizeConstraint inserido no botão SettingsButton.
    Janela de propriedades mostrando os valores esperados para o novo UISizeConstraint.
    Botão de configurações final na parte superior central da tela.

Criar o menu de configurações

O novo botão de configurações será scriptado para alternar um menu de configurações aberto e fechado, dando aos jogadores acesso sob demanda a configurações ou outras informações. Neste tutorial, o menu conterá controles deslizantes interativos para ajustar os níveis de volume do áudio de fundo e dos efeitos sonoros de forma independente.

Componentes básicos usados para o menu de configurações.

Criar o frame pai

Como mencionado em Criar medidores HUD, um Frame serve como um contêiner para outros objetos de UI. Todo o menu de configurações será construído com um único frame pai, tornando simples gerenciá-lo como um objeto com estado que reage à entrada de maneira diferente dependendo do estado atual.

  1. Insira um Frame dentro de HUDContainer e renomeie-o para SettingsMenu.

    Janela Explorer mostrando um novo frame inserido e renomeado para SettingsMenu.
  2. Com SettingsMenu selecionado, defina as seguintes propriedades:

    Frame reposicionado, redimensionado e estilizado com fundo azul marinho transparente.
  3. Insira um UIAspectRatioConstraint em SettingsMenu e defina sua propriedade AspectRatio para 2.5. (2.5:1 de largura para altura).

    Janela Explorer mostrando um novo UISizeConstraint inserido no frame SettingsMenu.
    Janela de propriedades mostrando os valores esperados para o novo UISizeConstraint.
  4. Insira um modificador UICorner em SettingsMenu e defina sua propriedade CornerRadius para 0.1, 0.

    Janela Explorer mostrando um novo UICorner inserido no frame SettingsMenu.
    Janela de propriedades mostrando os valores esperados para o novo modificador UICorner.
  5. Para restringir a largura e altura em pixels de SettingsMenu, insira um UISizeConstraint. Defina seu MaxSize para 800, inf e seu MinSize para 350, 0.

    Janela Explorer mostrando um novo UISizeConstraint inserido no frame SettingsMenu.
    Janela de propriedades mostrando os valores esperados para o novo UISizeConstraint.
    Frame estilizado com cantos arredondados.

Construir um controle deslizante

Para permitir que os jogadores ajustem os níveis de volume, o menu de configurações conterá dois widgets deslizantes arrastáveis, alimentados pelo UIDragDetector, um objeto conveniente que facilita a interação com elementos de interface do usuário 2D.


Para criar um contêiner pai para o primeiro controle deslizante:

  1. Insira um novo Frame no contêiner SettingsMenu e renomeie-o para EffectsVolumeSlider.

    Janela Explorer mostrando um novo frame inserido no frame SettingsMenu, renomeado para EffectsVolumeSlider.
  2. Com o frame EffectsVolumeSlider selecionado, defina as seguintes propriedades:

    • AnchorPoint = 0.5 (âncora central)
    • BackgroundTransparency = 1 (totalmente transparente)
    • Position = 0.5, 0, 0.35, 0 (centro horizontal e 35% da parte superior do contêiner)
    • Size = 0.8, 0, 0.1, 0 (80% da largura do contêiner e 10% de sua altura)
    Frame vazio inserido para conter os elementos deslizantes.
  3. Insira um novo UIListLayout em EffectsVolumeSlider. Este modificador de layout é uma maneira poderosa de auto-arranjar GuiObjects irmãos em linhas horizontais ou colunas verticais dentro de seu contêiner pai, incluindo a capacidade de aplicar conceitos de flex.

    Janela Explorer mostrando um novo UIListLayout inserido no frame EffectsVolumeSlider.
  4. Defina as seguintes propriedades para o novo UIListLayout:

    • Padding = 0.06, 0 (6% de preenchimento entre os elementos da lista)
    • FillDirection = Horizontal (arranjo de elementos da esquerda para a direita)
    • HorizontalFlex = Fill (redimensionar elementos horizontalmente para preencher todo o contêiner pai, substituindo sua largura definida)
    • VerticalAlignment = Center (alinhar elementos ao longo de seu centro vertical)

Ícone do controle deslizante

Um ícone simples que inclui uma nota musical e símbolo de "explosão" ajuda os jogadores a identificar o propósito do controle deslizante quando abrem o menu de configurações.

Ícone indicando o propósito do controle deslizante no menu de configurações.
  1. Insira um ImageLabel no frame EffectsVolumeSlider e renomeie-o para Icon. Este ícone ajudará os jogadores a entender qual aspecto da experiência o controle deslizante controla.

    Janela Explorer mostrando um ImageLabel inserido no frame EffectsVolumeSlider.
  2. Com Icon selecionado, defina as seguintes propriedades:

    • BackgroundTransparency = 1 (totalmente transparente)
    • Size = 2.5, 0, 2.5, 0 (250% da altura do frame pai uma vez que a proporção é restrita)
    • Image = rbxassetid://90019827067389 (ID do ativo da nota musical e símbolo de "explosão")
  3. Insira um UIAspectRatioConstraint em Icon e mantenha suas propriedades como os padrões (proporção 1:1 de largura para altura).

    Janela Explorer mostrando um UIAspectRatioConstraint inserido no ImageLabel. Ícone finalizado no menu de configurações.

Frame de intervalo

Diretamente à direita do ícone, a parte interativa do controle deslizante deve estar contida dentro de outro Frame.

Tamanho e posição desejados da parte interativa do controle deslizante.
  1. Insira um novo Frame no frame EffectsVolumeSlider e renomeie-o para SliderFrame. Observe que ele deve ser um irmão direto do modificador de layout UIListLayout.

    Janela Explorer mostrando um frame filho inserido no frame EffectsVolumeSlider.
  2. Com SliderFrame selecionado, defina as seguintes propriedades:

  3. Insira os seguintes modificadores em SliderFrame:

    Frame do controle deslizante posicionado à direita do ícone.

Manuseio interativo

Com o contêiner do controle deslizante construído, agora você pode criar um manipulador arrastável para os jogadores interagirem durante o jogo.

Manuseio interativo do controle deslizante posicionado dentro do frame de intervalo.
  1. Insira um novo Frame no contêiner SliderFrame e renomeie-o para Handle.

    Janela Explorer mostrando um frame filho inserido no frame SliderFrame e renomeado para Handle.
  2. Com Handle selecionado, defina as seguintes propriedades:

    • AnchorPoint = 0.5 (âncora central)
    • Position = 0.5, 0, 0.5, 0 (centro horizontal e vertical do frame pai)
    • Size = 1.2, 0, 1.2, 0 (120% da altura do frame pai uma vez que a proporção é restrita)
    • ZIndex = 3 (camada do manipulador visualmente na frente de outros elementos do controle deslizante)
  3. Insira os seguintes modificadores em Handle:

  4. Insira um objeto UIDragDetector em Handle. Este objeto conveniente facilita e incentiva a interação com elementos de interface do usuário 2D.

    Janela Explorer mostrando um UIDragDetector inserido no frame Handle.
  5. Defina as seguintes propriedades para o novo UIDragDetector:

  6. Para garantir que a faixa de arrasto linear do manipulador seja limitada ao seu contêiner, vincule sua propriedade BoundingUI ao contêiner SliderFrame:

    1. Selecione o UIDragDetector.
    2. Clique em sua propriedade BoundingUI na janela Propriedades.
    3. Na janela Explorer, clique no pai SliderFrame do manipulador.
    Diagrama mostrando o processo de vinculação da propriedade BoundingUI do detector ao contêiner SliderFrame.

    A propriedade BoundingUI agora reflete o contêiner SliderFrame:

    Janela de propriedades mostrando a propriedade BoundingUI do detector vinculada ao contêiner SliderFrame.

Se você testar a experiência agora, poderá arrastar o manipulador para a esquerda e para a direita dentro de seu contêiner pai:

Preenchimento interno

Para indicar mais claramente que o controle deslizante controla um intervalo de 0% a 100%, você pode adicionar um preenchimento interno ao lado esquerdo do contêiner que irá sincronizar com a posição variável do manipulador.

Porção interna do controle deslizante inserida no SliderFrame.
  1. Insira um novo Frame no contêiner SliderFrame e renomeie-o para InnerFill.

    Janela Explorer mostrando um frame filho inserido no frame SliderFrame e renomeado para InnerFill.
  2. Defina as seguintes propriedades para o frame InnerFill:

    • AnchorPoint = 0, 0.5 (borda esquerda e centro vertical)
    • BackgroundColor3 = [0, 150, 255] (azul combinando com o manipulador do controle deslizante)
    • BackgroundTransparency = 0.35 (65% opaco)
    • Position = 0, 0, 0.5, 0
    • Size = 0.5, 0, 1, 0 (50% de largura e 100% de altura do frame pai)
    • ZIndex = 2 (camada visualmente na frente do preenchimento/contorno do frame pai)
  3. Para combinar com a forma de "pílula" do contêiner pai SliderFrame, insira um modificador UICorner e defina sua propriedade CornerRadius para 0.5, 0.

    Janela Explorer mostrando um modificador UICorner inserido no frame InnerFill.
    Janela de propriedades mostrando os valores esperados para o novo UICorner.
    Frame InnerFill estilizado com fundo azul e cantos arredondados.

Duplicar o controle deslizante

Com o primeiro controle deslizante construído, você pode facilmente duplicá-lo e modificar alguns aspectos visuais para indicar outro propósito, neste caso, o nível de volume do áudio de fundo simbolizado por um ícone de notas musicais.

Posição alvo do controle deslizante de áudio de fundo.
  1. Selecione o objeto EffectsVolumeSlider completo.

    Janela Explorer mostrando o EffectsVolumeSlider completo selecionado.
  2. Duplicá-lo (CtrlD ou D) e renomeie a duplicata para BackgroundVolumeSlider.

    Janela Explorer mostrando o controle deslizante duplicado renomeado para BackgroundVolumeSlider.
  3. Altere a Position da duplicata para 0.5, 0, 0.7, 0 para movê-la para abaixo do primeiro controle deslizante.

    BackgroundVolumeSlider posicionado abaixo de EffectsVolumeSlider.
  4. Expanda o ramo de nível superior de BackgroundVolumeSlider, selecione o rótulo da imagem Icon e altere sua propriedade Image para rbxassetid://101125859760167 (ID do ativo do símbolo com notas musicais).

    Janela Explorer mostrando o rótulo Icon dentro de BackgroundVolumeSlider.
    Janela de propriedades mostrando os valores esperados para o rótulo Icon.
    BackgroundVolumeSlider com ícone de imagem modificado.
  5. Expanda o ramo SliderFrameHandle, selecione o modificador UIStroke dentro, e defina sua propriedade Color para [255, 0, 125] (magenta).

    Janela Explorer mostrando o modificador UIStroke dentro do manipulador de BackgroundVolumeSlider.
    Janela de propriedades mostrando os valores esperados para o modificador UIStroke.
    BackgroundVolumeSlider com ícone de imagem modificado.
  6. Selecione o frame InnerFill dentro de SliderFrame e altere sua propriedade BackgroundColor3 para a mesma cor magenta ([255, 0, 125]).

    Janela Explorer mostrando o frame InnerFill dentro do contêiner SliderFrame de BackgroundVolumeSlider.
    Janela de propriedades mostrando os valores esperados para o frame InnerFill.
    BackgroundVolumeSlider com cor InnerFill modificada.

Criar o botão de fechar

O último elemento do menu de configurações é um botão de fechar que fornece aos jogadores uma entrada adicional para fechar o menu (o SettingsButton no centro superior servirá ao mesmo propósito).

Menu de configurações com o botão de fechar indicado no canto superior direito.
  1. Insira um novo ImageButton no contêiner SettingsMenu e renomeie-o para CloseButton.

    Janela Explorer mostrando um novo ImageButton inserido no SettingsMenu e renomeado para CloseButton. ImageButton vazio posicionado no canto superior esquerdo do menu de configurações.
  2. Com CloseButton selecionado, defina as seguintes propriedades:

    • AnchorPoint = 1, 0 (canto superior direito)
    • BackgroundTransparency = 1 (totalmente transparente)
    • Position = 1, -10, 0, 10 (10 pixels para dentro a partir do canto superior direito)
    • Size = 0.15, 0, 0.15, 0 (15% da altura do frame uma vez que a proporção é restringida)
    • Image = rbxassetid://5577404210 (ID do ativo do símbolo do botão de fechar)
    • ImageTransparency = 0.25 (75% opaco)
  3. Insira um UIAspectRatioConstraint no botão com propriedades padrão (proporção 1:1 de largura para altura).

    Janela Explorer mostrando um UIAspectRatioConstraint inserido no botão CloseButton. Botão de fechar finalizado posicionando-se no canto superior direito do menu de configurações.

Criar os módulos de controle

Uma configuração de módulo de controle extensível torna o gerenciamento de UI interativa mais simplificado do que scripts individuais colocados dentro de cada objeto. ModuleScripts facilitam essa funcionalidade extensível permitindo que você reutilize código entre scripts em diferentes lados da fronteira cliente-servidor ou no mesmo lado da fronteira.

Controlador de objeto com estado

O seguinte módulo controlador de objeto com estado permite que você anexe comportamentos a objetos de UI como SettingsButton e SettingsMenu, e facilmente alternar/animar entre vários estados. Para criar o módulo:

  1. Insira um ModuleScript no contêiner ReplicatedStorage e renomeie-o para StatefulObjectController.

    Janela Explorer mostrando o módulo StatefulObjectController dentro do contêiner ReplicatedStorage.
  2. Cole o seguinte código dentro do módulo:

    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)
    -- Crie tweens para reutilização para evitar fazer novos tweens toda vez que o estado é alterado
    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("Tentou definir %s para um estado desconhecido '%s'", self.object:GetFullName(), stateName))
    return
    end
    self.currentStateName = stateName
    -- Certifique-se de que outros tweens não estejam em conflito
    for _, tween in self.tweens do
    tween:Cancel()
    end
    stateTween:Play()
    end
    return StatefulObjectController
    LinhasPropósito
    610Define e exporta os tipos Luau para melhorar a autocompletação e verificação ao usar este módulo.
    1233Função usada para inicializar e anexar comportamento a um objeto de UI com estado, aceitando um GuiObject como object, uma tabela de estados e seus respectivos dados TweenInfo, e um nome de estado inicial. Dentro dessa função, as linhas 2628 constroem Tweens para cada estado, e a linha 30 chama a função setState() do módulo para definir o objeto ao estado inicial.
    3550Função usada para definir/mudar o estado de um objeto com estado. A linha 42 define o currentStateName do objeto para o estado que está sendo definido, as linhas 4547 cancelam quaisquer tweens em execução para evitar conflitos, e a linha 49 executa o(s) tween(s) do estado.

Controlador do deslizante

Um módulo adicional inicializa e controla os dois controles deslizantes de volume. Ele também permite que você conecte uma função de retorno de chamada a cada controle deslizante para detectar a interação do jogador com o controle deslizante e aplicar as alterações desejadas na experiência.

  1. Insira um ModuleScript no contêiner ReplicatedStorage e renomeie-o para SliderController.

    Janela Explorer mostrando o módulo SliderController dentro do contêiner ReplicatedStorage.
  2. Cole o seguinte código dentro do módulo:

    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("Tentou hidratar o controle deslizante %s mas não conseguiu encontrar o Handle", object:GetFullName()))
    end
    local innerFill = object:FindFirstChild("InnerFill", true)
    if not innerFill then
    warn(string.format("Tentou hidratar o controle deslizante %s mas não conseguiu encontrar o InnerFill", object:GetFullName()))
    end
    local dragDetector = handle:FindFirstChildWhichIsA("UIDragDetector")
    if not dragDetector then
    warn(string.format("Tentou hidratar o controle deslizante %s mas não conseguiu encontrar o UIDragDetector", object:GetFullName()))
    end
    local self = setmetatable({
    handle = handle,
    innerFill = innerFill,
    dragDetector = dragDetector,
    value = initialValue or 0.5,
    onChanged = onChanged,
    }, SliderController)
    -- Defina o valor inicial
    self:setValue(self.value)
    -- Conecte o detector à manipulação do jogador
    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
    -- Atualize a posição do manipulador e o tamanho do inner fill para combinar
    self.handle.Position = UDim2.fromScale(clampedValue, 0.5)
    self.innerFill.Size = UDim2.fromScale(clampedValue, 1)
    -- Execute a função de retorno de chamada do usuário com o valor mais recente
    local changeSuccess, changeResult = pcall(self.onChanged, clampedValue)
    if not changeSuccess then
    warn("Erro na callback do controle deslizante:", changeResult)
    end
    end
    return SliderController
    LinhasPropósito
    746Função usada para inicializar e anexar comportamento a um elemento de controle deslizante, aceitando o pai do controle deslizante Frame como object, uma função de callback onChanged para processar alterações do controle deslizante, e um valor inicial para a posição do manipulador do controle deslizante. Dentro da função, as linhas 1427 confirmam que os elementos do manipulador, preenchimento interno e UIDragDetector existem. A linha 38 chama a função setValue() do módulo e as linhas 4143 conectam o evento DragContinue do detector de arrasto à função setValue() do módulo (veja a linha seguinte para mais detalhes).
    4861Função usada para definir o valor do controle deslizante. Dentro da função, as linhas 5354 garantem que a posição do manipulador e o tamanho do preenchimento interno estejam sincronizados, e a linha 57 passa o valor alterado para a função de retorno de chamada, para que você possa utilizar o valor conforme necessário.

Criar o script de configurações

Com o botão de configurações e o menu de configurações finalizados, você pode conectar tudo com um único script que utiliza os módulos de controle.

  1. Insira um novo LocalScript dentro de HUDContainer e renomeie-o para SettingsScript para descrever seu propósito. Observe que este script deve estar no mesmo nível (irmão) que SettingsMenu e SettingsButton, os objetos de UI de nível superior que irá gerenciar.

    Janela Explorer mostrando o script SettingsScript dentro do contêiner HUDContainer.
  2. Cole o seguinte código dentro do script:

    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
    -- Inicializa o botão de configurações
    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"
    })
    -- Inicializa o frame do menu de configurações
    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"
    })
    -- Inicializa o controle deslizante de volume de efeitos
    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,
    })
    -- Inicializa o controle deslizante de volume de fundo
    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,
    })
    -- Conecta botões à interação do jogador
    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. Consulte as seguintes seções para explorar como o script utiliza os módulos de controle.

    As linhas 10-27 inicializam e anexam comportamento ao botão de configurações da seguinte maneira:

    LinhasPropósito
    1011Uma referência local settingsButton é declarada e hidratada com a função StatefulObjectController.hydrate(), e o SettingsButton dentro do HUDContainer é referenciado como o objeto a ser hidratado.
    1225Uma tabela states é passada com dois estados exclusivos, menuOpen e menuClosed. Cada estado contém uma transição para declarar (através de um TweenInfo) como o estado particular alcançará suas propriedades-alvo definidas na tabela properties. Neste caso, menuOpen declara uma mudança de estado para 45° para a rotação do botão Rotation com um tween Exponential de meio segundo, enquanto que menuClosed efetivamente restaura o botão à sua rotação padrão de 0.
    26O estado inicial do botão é definido como menuClosed (isso poderia ser definido como qualquer nome de estado dentro da tabela states).

    Mais adiante no script (linhas 76-86), os botões são conectados à interação do jogador para acionar alterações no estado da UI:

    LinhasPropósito
    7682SettingsButton está conectado ao evento Activated da classe GuiButton para chamar uma função anônima. Dentro da função anônima, as linhas 7779 alternam uma variável targetState entre menuOpen e menuClosed. A linha 80 então chama setState() para definir o estado do botão como targetState e a linha 81 faz o mesmo para SettingsMenu, de modo que ele alterna entre aberto ou fechado com a ativação do SettingsButton.
    8386CloseButton está conectado ao evento Activated para chamar uma função anônima que define o estado de ambos SettingsButton e SettingsMenu como menuClosed.

    As linhas 30-49 inicializam e anexam comportamento ao menu de configurações da seguinte maneira:

    LinhasPropósito
    3031Uma referência local settingsMenu é declarada e hidratada com a função StatefulObjectController.hydrate() e o frame SettingsMenu dentro do HUDContainer é referenciado como o objeto a ser hidratado.
    3246Semelhante ao botão de configurações, uma tabela states é passada com dois estados exclusivos, menuOpen e menuClosed. Aqui, menuOpen declara uma mudança de estado para UDim2.fromScale(0.5, 0.5) para a Position do frame com um tween Bounce de meio segundo, bem como um estado Visible de true. Em contraste, menuClosed declara uma mudança de estado posicional para UDim2.fromScale(0.5, 0.4) e Visible para false, mas o TweenInfo com duração 0 na linha 41 efetivamente faz com que a mudança de estado ocorra instantaneamente.
    48O estado inicial do frame é definido como menuClosed.

    Mais adiante no script (linhas 76-86), o menu de configurações é vinculado à interação do jogador:

    LinhasPropósito
    81Define o mesmo targetState para SettingsMenu para sincronizar com a ativação do SettingsButton.
    85Define o estado de SettingsMenu como menuClosed quando o CloseButton é ativado.

    As linhas 51-73 inicializam e anexam comportamento aos EffectsVolumeSlider e BackgroundVolumeSlider da seguinte maneira:

    LinhasPropósito
    52Define uma referência local ao grupo de sons Effects dentro de SoundService. Um SoundGroup permite relacionar múltiplos Sounds e controlar o volume de cada som no grupo através da propriedade Volume do grupo.
    5354Uma referência local effectsVolumeSlider é declarada e hidratada com a função SliderController.hydrate() e o frame EffectsVolumeSlider dentro do HUDContainer ⟩ SettingsMenu é referenciado como o objeto a ser hidratado. Observe que o segundo parâmetro de true para FindFirstChild() diz ao método para procurar recursivamente na ramificação HUDContainer para localizar EffectsVolumeSlider.
    55O valor inicial do controle deslizante é definido como o Volume atual do grupo de sons Effects, ou 0.5 como fallback.
    5660Estabelece a função de callback para aplicar alterações de valor do controle deslizante ao volume do grupo de sons Effects.
    6473Essencialmente o mesmo que as linhas 52-61, exceto que hidrata o frame BackgroundVolumeSlider dentro do HUDContainer ⟩ SettingsMenu e aplica as alterações de valor do controle deslizante ao volume do grupo de sons Background.

Com o SettingsScript em funcionamento, a experiência agora oferece um exemplo de UI interativa totalmente operacional que vincula um conjunto relacionado de objetos de UI à interação do jogador.

©2026 Roblox Corporation, Roblox, o logotipo Roblox e Powering Imagination estão entre nossas marcas registradas e não registradas nos EUA e em outros países.