Tutoriales intermedios

Crear UI interactiva

*Este contenido se traduce usando la IA (Beta) y puede contener errores. Para ver esta página en inglés, haz clic en aquí.

Un HUD (Heads-Up Display) en tu experiencia comúnmente muestra elementos de UI no interactivos, como el medidor de salud demostrado en Crear medidores HUD. Además de esto, casi toda experiencia requiere UI interactiva como botones que responden a la activación del jugador, que se animan al ser activados, que muestran menús con animación in/out junto con otros controles interactivos, etc.

Vista del juego mostrando un botón de configuración y un menú de configuración con deslizadores de volumen.

Usando Fundamentos de UI - Medidor HUD como un punto de partida y Fundamentos de UI - Interactividad como un lugar de referencia terminado, este tutorial demuestra:

  • Cómo colocar un botón de configuración a lo largo del borde superior de la pantalla.
  • Diseño de un menú de configuración que contiene deslizadores interactivos que se pueden desplazar.
  • Uso de un ModuleScripts para formar módulos de "controlador" para control extensible de objetos de UI con declaraciones de estado.
  • Cómo conectar botones a la activación del jugador para alternar el menú de configuración.
  • Cómo conectar deslizadores de UI interactivos para ajustar el volumen de los efectos de sonido y la ambientación de fondo por separado.

Habilitar el emulador de dispositivos

Como se menciona en Crear medidores HUD, los teléfonos y tabletas tienen la menor cantidad de espacio en pantalla, por lo que es importante que tus elementos de UI se ajusten a pantallas más pequeñas y que sean claramente visibles para los jugadores. Si aún no lo has hecho, habilita el Emulador de Dispositivos en Studio:

  1. Abre la plantilla Fundamentos de UI - Medidor HUD en Studio.

  2. Desde el menú Prueba de Studio, activa el Emulador de Dispositivos.

  3. Desde la barra directamente encima de la ventana principal, selecciona una emulación de teléfono como iPhone X o Samsung Galaxy A51. Luego, establece el tamaño de vista en Ajustar a la ventana para utilizar el espacio máximo en Studio.

    Opciones de configuración del Emulador de Dispositivos indicadas en la parte superior de la ventana de vista.

Crear el botón de configuración

GuiButtons son elementos de interfaz de usuario interactiva con funcionalidad integrada, como el evento multiplataforma Activated que se activa cuando se hace clic o se toca el botón. La clase GuiButton se extiende a dos variaciones, TextButton y ImageButton, y este tutorial utiliza un ImageButton con forma de "engranaje" para alternar el menú de configuración abrirlo o cerrarlo.

Componente de Roblox utilizado para el botón de configuración.

Para construir el botón de configuración:

  1. En la ventana Explorador, localiza HUDContainer dentro de StarterGui.

    Ventana del explorador mostrando el HUDContainer seleccionado.
  2. Inserta un ImageButton en HUDContainer y renómbralo a SettingsButton.

    Ventana del explorador mostrando un nuevo ImageButton insertado y renombrado a SettingsButton. Nuevo ImageButton en la vista.
  3. Con el nuevo botón seleccionado, establece lo siguiente en la ventana Propiedades:

    • AnchorPoint = 0.5, 0.25 (centro horizontal y cuarto superior vertical)
    • BackgroundTransparency = 1 (totalmente transparente)
    • Position = 0.5, 0, 0, 0 (posicionamiento en el centro superior)
    • Size = 0.1, 0, 0.1, 0 (10% de la altura de la pantalla una vez que se restringe la relación de aspecto)
    • Image = rbxassetid://104919049969988 (ID de activo del símbolo de "engranaje")
  4. Inserta un UIAspectRatioConstraint en el botón con propiedades predeterminadas (proporción de 1:1 de ancho a alto).

    Ventana del explorador mostrando un nuevo UIAspectRatioConstraint insertado en el botón SettingsButton.
  5. Para limitar la altura máxima en píxeles del botón, inserta un UISizeConstraint y establece su MaxSize a inf, 44.

    Ventana del explorador mostrando un nuevo UISizeConstraint insertado en el botón SettingsButton.
    Ventana de propiedades mostrando los valores esperados para el nuevo UISizeConstraint.
    Botón de configuración finalizado en el centro superior de la pantalla.

Crear el menú de configuración

El nuevo botón de configuración será programado para alternar un menú de configuración abierto y cerrado, dando a los jugadores acceso a demanda a configuraciones u otra información. En este tutorial, el menú contendrá deslizadores interactivos para ajustar los niveles de volumen del audio de fondo y los efectos de sonido de forma independiente.

Componentes básicos utilizados para el menú de configuración.

Crear el marco principal

Como se menciona en Crear medidores HUD, un Frame sirve como contenedor para otros objetos de UI. Todo el menú de configuración se construirá con un solo marco principal, lo que facilita su gestión como un objeto con estado que reacciona a la entrada de manera diferente dependiendo del estado actual.

  1. Inserta un Frame en HUDContainer y renómbralo SettingsMenu.

    Ventana del explorador mostrando un nuevo marco insertado y renombrado a SettingsMenu.
  2. Con SettingsMenu seleccionado, establece las siguientes propiedades:

    Marco reposicionado, redimensionado y estilizado con un fondo azul marino transparente.
  3. Inserta un UIAspectRatioConstraint en SettingsMenu y establece su AspectRatio a 2.5. (2.5:1 de ancho a alto).

    Ventana del explorador mostrando un nuevo UISizeConstraint insertado en el marco SettingsMenu.
    Ventana de propiedades mostrando los valores esperados para el nuevo UISizeConstraint.
  4. Inserta un modificador UICorner en SettingsMenu y establece su CornerRadius a 0.1, 0.

    Ventana del explorador mostrando un nuevo UICorner insertado en el marco SettingsMenu.
    Ventana de propiedades mostrando los valores esperados para el nuevo modificador UICorner.
  5. Para restringir el ancho y la altura en píxeles de SettingsMenu, inserta un UISizeConstraint. Establece su MaxSize a 800, inf y su MinSize a 350, 0.

    Ventana del explorador mostrando un nuevo UISizeConstraint insertado en el marco SettingsMenu.
    Ventana de propiedades mostrando los valores esperados para el nuevo UISizeConstraint.
    Marco estilizado con esquinas redondeadas.

Construir un deslizador

Para permitir que los jugadores ajusten los niveles de volumen, el menú de configuración contendrá dos widgets deslizadores que funcionan con UIDragDetector, un objeto conveniente que facilita la interacción con elementos de la interfaz de usuario 2D.


Para crear un contenedor principal para el primer deslizador:

  1. Inserta un nuevo Frame en el contenedor SettingsMenu y renómbralo EffectsVolumeSlider.

    Ventana del explorador mostrando un nuevo marco insertado en el marco SettingsMenu, renombrado a EffectsVolumeSlider.
  2. Con el marco EffectsVolumeSlider seleccionado, establece las siguientes propiedades:

    • AnchorPoint = 0.5 (anclaje al centro)

    • BackgroundTransparency = 1 (totalmente transparente)

    • Position = 0.5, 0, 0.35, 0 (centro horizontal y 35% desde la parte superior del contenedor)

    • Size = 0.8, 0, 0.1, 0 (80% de ancho del contenedor y 10% de su altura)

      Marco vacío insertado para contener elementos deslizadores.
  3. Inserta un nuevo UIListLayout en EffectsVolumeSlider. Este modificador de diseño es una forma poderosa de organizar automáticamente los GuiObjects hermanos en filas horizontales o columnas verticales dentro de su contenedor padre, incluyendo la capacidad de aplicar conceptos de flexibilidad.

    Ventana del explorador mostrando un nuevo UIListLayout insertado en el marco EffectsVolumeSlider.
  4. Establece las siguientes propiedades para el nuevo UIListLayout:

    • Padding = 0.06, 0 (6% de relleno entre los elementos de la lista)
    • FillDirection = Horizontal (organización de izquierda a derecha de los elementos)
    • HorizontalFlex = Fill (redimensionar elementos horizontalmente para llenar todo el contenedor padre, anulando su ancho definido)
    • VerticalAlignment = Center (alinear elementos a lo largo de su centro vertical)

Icono del deslizador

Un icono simple que incluye una nota de audio y un símbolo de "explosión" ayuda a los jugadores a identificar la finalidad del deslizador cuando abren el menú de configuración.

Icono que indica la finalidad del deslizador en el menú de configuración.
  1. Inserta un ImageLabel en el marco EffectsVolumeSlider y renómbralo a Icon. Este icono ayudará a los jugadores a entender qué aspecto de la experiencia controla el deslizador.

    Ventana del explorador mostrando un ImageLabel insertado en el marco EffectsVolumeSlider.
  2. Con Icon seleccionado, establece las siguientes propiedades:

    • BackgroundTransparency = 1 (totalmente transparente)
    • Size = 2.5, 0, 2.5, 0 (250% de la altura del marco padre una vez que se restringe la relación de aspecto)
    • Image = rbxassetid://90019827067389 (ID de activo de la nota de audio y símbolo de "explosión")
  3. Inserta un UIAspectRatioConstraint en Icon y deja sus propiedades como los valores predeterminados (1:1 de ancho a alto).

    Ventana del explorador mostrando un UIAspectRatioConstraint insertado en el ImageLabel. Icono finalizado en el menú de configuración.

Marco de rango

Justo a la derecha del icono, la porción interactiva del deslizador debe estar contenida dentro de otro Frame.

Tamaño y posición objetivos de la porción interactiva del deslizador.
  1. Inserta un nuevo Frame en el marco EffectsVolumeSlider y renómbralo SliderFrame. Ten en cuenta que debe ser un hermano directo del modificador de diseño UIListLayout.

    Ventana del explorador mostrando un marco hijo insertado en el marco EffectsVolumeSlider.
  2. Con SliderFrame seleccionado, establece las siguientes propiedades:

  3. Inserta los siguientes modificadores en SliderFrame:

    Marco deslizante posicionado a la derecha del icono.

Mango interactivo

Con el contenedor del deslizador construido, ahora puedes crear un mango arrastrable para que los jugadores interactúen durante el juego.

Mango de deslizador interactivo posicionado dentro del marco de rango.
  1. Inserta un nuevo Frame en el contenedor SliderFrame y renómbralo a Handle.

    Ventana del explorador mostrando un marco hijo insertado en el marco SliderFrame y renombrado a Handle.
  2. Con Handle seleccionado, establece las siguientes propiedades:

    • AnchorPoint = 0.5 (anclaje al centro)
    • Position = 0.5, 0, 0.5, 0 (centro horizontal y vertical del marco padre)
    • Size = 1.2, 0, 1.2, 0 (120% de la altura del marco padre una vez que se restringe la relación de aspecto)
    • ZIndex = 3 (capa de mango visualmente en frente de otros elementos del deslizador)
  3. Inserta los siguientes modificadores en Handle:

  4. Inserta un objeto UIDragDetector en Handle. Este objeto conveniente facilita y fomenta la interacción con elementos de la interfaz de usuario 2D.

    Ventana del explorador mostrando un UIDragDetector insertado en el marco Handle.
  5. Establece las siguientes propiedades para el nuevo UIDragDetector:

  6. Para asegurarte de que el rango de arrastre lineal del mango esté limitado a su contenedor, vincula su propiedad BoundingUI al contenedor SliderFrame:

    1. Selecciona el UIDragDetector.
    2. Haz clic en su propiedad BoundingUI en la ventana Propiedades.
    3. De regreso en la ventana Explorador, haz clic en el padre del mango SliderFrame.
    Diagrama que muestra el proceso de vinculación de la propiedad BoundingUI del detector al contenedor SliderFrame.

    Ahora la vinculación de la propiedad BoundingUI refleja el contenedor SliderFrame:

    Ventana de propiedades mostrando la propiedad BoundingUI del detector vinculada al contenedor SliderFrame.

Si pruebas la experiencia ahora, ¡podrás arrastrar el mango de izquierda a derecha dentro de su contenedor padre!

Relleno interno

Para indicar más claramente que el deslizador controla un rango del 0% al 100%, puedes añadir un relleno interno al lado izquierdo del contenedor que se sincronizará con la posición variable del mango.

Porción de relleno interno del deslizador insertada en SliderFrame.
  1. Inserta un nuevo Frame en el contenedor SliderFrame y renómbralo a InnerFill.

    Ventana del explorador mostrando un marco hijo insertado en el marco SliderFrame y renombrado a InnerFill.
  2. Establece las siguientes propiedades para el marco InnerFill:

    • AnchorPoint = 0, 0.5 (borde izquierdo y centro vertical)
    • BackgroundColor3 = [0, 150, 255] (azul que coincide con el mango del deslizador)
    • BackgroundTransparency = 0.35 (65% opaco)
    • Position = 0, 0, 0.5, 0
    • Size = 0.5, 0, 1, 0 (50% de ancho y 100% de altura del marco padre)
    • ZIndex = 2 (capa visualmente delante del relleno/borde del marco padre)
  3. Para igualar la forma de "píldora" del contenedor padre SliderFrame, inserta un modificador UICorner y establece su propiedad CornerRadius en 0.5, 0.

    Ventana del explorador mostrando un modificador UICorner insertado en el marco InnerFill.
    Ventana de propiedades mostrando los valores esperados para el nuevo UICorner.
    Marco InnerFill estilizado con fondo azul y esquinas redondeadas.

Duplicar el deslizador

Con el primer deslizador construido, puedes duplicarlo fácilmente y modificar algunos aspectos visuales para indicar otra finalidad, en este caso el nivel de volumen del audio de fondo simbolizado por un icono de notas musicales.

Posición objetivo del deslizador de audio de fondo.
  1. Selecciona el objeto EffectsVolumeSlider completado.

    Ventana del explorador mostrando el EffectsVolumeSlider completo seleccionado.
  2. Duplicalo (CtrlD o D) y luego cambia el nombre del duplicado a BackgroundVolumeSlider.

    Ventana del explorador mostrando el deslizador duplicado renombrado a BackgroundVolumeSlider.
  3. Cambia la propiedad Position del duplicado a 0.5, 0, 0.7, 0 para moverlo por debajo del primer deslizador.

    BackgroundVolumeSlider posicionado por debajo del EffectsVolumeSlider.
  4. Expande la rama de nivel superior de BackgroundVolumeSlider, selecciona la etiqueta de imagen Icon y cambia su propiedad Image a rbxassetid://101125859760167 (ID de activo del símbolo con notas musicales).

    Ventana del explorador mostrando la etiqueta Icon dentro de BackgroundVolumeSlider.
    Ventana de propiedades mostrando los valores esperados para la etiqueta Icon.
    BackgroundVolumeSlider con la imagen del icono modificada.
  5. Expande la rama SliderFrameHandle, selecciona el modificador UIStroke dentro, y establece su propiedad Color en [255, 0, 125] (magenta).

    Ventana del explorador mostrando el modificador UIStroke dentro del mango de BackgroundVolumeSlider.
    Ventana de propiedades mostrando los valores esperados para el modificador UIStroke.
    BackgroundVolumeSlider con la imagen del icono modificada.
  6. Selecciona el marco InnerFill dentro de SliderFrame y cambia su propiedad BackgroundColor3 al mismo color magenta ([255, 0, 125]).

    Ventana del explorador mostrando el marco InnerFill dentro del contenedor SliderFrame de BackgroundVolumeSlider.
    Ventana de propiedades mostrando los valores esperados para el marco InnerFill.
    BackgroundVolumeSlider con el color de InnerFill modificado.

Crear el botón de cerrar

El elemento final del menú de configuración es un botón de cerrar que proporciona a los jugadores una entrada adicional para cerrar el menú (el SettingsButton en el centro superior cumplirá la misma función).

Menú de configuración con el botón de cerrar indicado en la esquina superior derecha.
  1. Inserta un nuevo ImageButton en el contenedor SettingsMenu y renómbralo CloseButton.

    Ventana del explorador mostrando un nuevo ImageButton insertado en SettingsMenu y renombrado a CloseButton. Botón de imagen vacío posicionado en la esquina superior izquierda del menú de configuración.
  2. Con CloseButton seleccionado, establece las siguientes propiedades:

    • AnchorPoint = 1, 0 (esquina superior derecha)
    • BackgroundTransparency = 1 (totalmente transparente)
    • Position = 1, -10, 0, 10 (10 píxeles de margen desde la esquina superior derecha)
    • Size = 0.15, 0, 0.15, 0 (15% de la altura del marco una vez que se restringe la relación de aspecto)
    • Image = rbxassetid://5577404210 (ID de activo del símbolo del botón de cerrar)
    • ImageTransparency = 0.25 (75% opaco)
  3. Inserta un UIAspectRatioConstraint en el botón con propiedades predeterminadas (1:1 de ancho a alto).

    Ventana del explorador mostrando un UIAspectRatioConstraint insertado en el botón CloseButton. Botón de cerrar finalizado en la esquina superior derecha del menú de configuración.

Crear los módulos de control

Un setup de módulo de control extensible hace que la gestión de UI interactiva sea más fluida que scripts individuales colocados dentro de cada objeto. ModuleScripts facilitan esta funcionalidad extensible permitiéndote reutilizar código entre scripts de lados diferentes de la frontera cliente-servidor o del mismo lado de la frontera.

Controlador de objeto con estado

El siguiente módulo del controlador de objeto con estado te permite adjuntar comportamiento a objetos de UI como SettingsButton y SettingsMenu, y alternar/facilitar fácilmente entre varios estados. Para crear el módulo:

  1. Inserta un ModuleScript en el contenedor ReplicatedStorage y renómbralo a StatefulObjectController.

    Ventana del explorador mostrando el módulo StatefulObjectController dentro del contenedor ReplicatedStorage.
  2. Pega el siguiente código dentro del 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)
    -- Crear tweens para reutilizarlos para evitar crear nuevos tweens cada vez que se cambia el estado
    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("Intento de establecer %s a un estado desconocido '%s'", self.object:GetFullName(), stateName))
    return
    end
    self.currentStateName = stateName
    -- Asegúrate de que otros tweens no estén en conflicto
    for _, tween in self.tweens do
    tween:Cancel()
    end
    stateTween:Play()
    end
    return StatefulObjectController
    FilasPropósito
    610Define y exporta los tipos de Luau para mejorar el autocompletado y la verificación de errores al usar este módulo.
    1233Función utilizada para inicializar y adjuntar comportamiento a un objeto de UI con estado, aceptando un GuiObject como object, una tabla de estados y sus respectivos datos TweenInfo, y un nombre de estado inicial. Dentro de esta función, las líneas 2628 construyen Tweens para cada estado, y la línea 30 llama a la función setState() del módulo para establecer el objeto en el estado inicial.
    3550Función utilizada para establecer/cambiar el estado de un objeto con estado. La línea 42 establece el currentStateName del objeto al estado que se está estableciendo, las líneas 4547 cancelan cualquier tween en ejecución para evitar conflictos, y la línea 49 ejecuta el/los tween(s) del estado.

Controlador del deslizador

Un módulo adicional inicializa y controla los dos deslizadores de volumen. También te permite conectar una función de callback a cada deslizador para detectar la interacción del jugador con el deslizador y aplicar los cambios deseados en la experiencia.

  1. Inserta un ModuleScript en el contenedor ReplicatedStorage y renómbralo a SliderController.

    Ventana del explorador mostrando el módulo SliderController dentro del contenedor ReplicatedStorage.
  2. Pega el siguiente código dentro del 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("Intento de hidratar el deslizador %s pero no se pudo encontrar Handle", object:GetFullName()))
    end
    local innerFill = object:FindFirstChild("InnerFill", true)
    if not innerFill then
    warn(string.format("Intento de hidratar el deslizador %s pero no se pudo encontrar InnerFill", object:GetFullName()))
    end
    local dragDetector = handle:FindFirstChildWhichIsA("UIDragDetector")
    if not dragDetector then
    warn(string.format("Intento de hidratar el deslizador %s pero no se pudo encontrar UIDragDetector", object:GetFullName()))
    end
    local self = setmetatable({
    handle = handle,
    innerFill = innerFill,
    dragDetector = dragDetector,
    value = initialValue or 0.5,
    onChanged = onChanged,
    }, SliderController)
    -- Establecer valor inicial
    self:setValue(self.value)
    -- Conectar el detector para manipulación por parte del jugador
    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
    -- Actualizar la posición del mango y el tamaño del marco interior para que coincidan
    self.handle.Position = UDim2.fromScale(clampedValue, 0.5)
    self.innerFill.Size = UDim2.fromScale(clampedValue, 1)
    -- Ejecutar el callback del usuario con el último valor
    local changeSuccess, changeResult = pcall(self.onChanged, clampedValue)
    if not changeSuccess then
    warn("Error en el callback del deslizador:", changeResult)
    end
    end
    return SliderController
    FilasPropósito
    746Función utilizada para inicializar y adjuntar comportamiento a un elemento deslizador, aceptando el Frame padre del deslizador como object, una función de callback onChanged para procesar los cambios del deslizador, y un valor inicial para la posición del mango del deslizador. Dentro de la función, las líneas 1427 confirman que existen el mango del deslizador, el relleno interior y los elementos UIDragDetector. La línea 38 llama a la función setValue() del módulo y las líneas 4143 conectan el evento DragContinue del detector a la función setValue() del módulo (ver la siguiente fila para más detalles).
    4861Función utilizada para establecer el valor del deslizador. Dentro de la función, las líneas 5354 aseguran que la posición del mango y el tamaño del relleno interno estén sincronizados, y la línea 57 pasa el valor cambiado a la función de callback para que puedas utilizar el valor como sea necesario.

Crear el script de configuración

Con el botón de configuración y el menú de configuración finalizados, puedes conectar todo con un solo script que utilice los módulos de control.

  1. Inserta un nuevo LocalScript en HUDContainer y renómbralo a SettingsScript para describir su propósito. Ten en cuenta que este script debe estar al mismo nivel (hermano) que SettingsMenu y SettingsButton, los objetos de UI de nivel superior que gestionará.

    Ventana del explorador mostrando el script SettingsScript dentro del contenedor HUDContainer.
  2. Pega el siguiente código dentro del 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
    -- Inicializar botón de configuración
    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"
    })
    -- Inicializar marco del menú de configuración
    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"
    })
    -- Inicializar deslizador de volumen de efectos
    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,
    })
    -- Inicializar deslizador de volumen de fondo
    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,
    })
    -- Conectar botones a la interacción del jugador
    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. Consulta las siguientes secciones para explorar cómo el script utiliza los módulos de control.

    Las líneas 10-27 inicializan y adjuntan comportamiento al botón de configuración de la siguiente manera:

    FilasPropósito
    1011Se declara una referencia local settingsButton y se hidrata con la función StatefulObjectController.hydrate(), y el botón SettingsButton dentro de HUDContainer se referencia como el objeto a hidratar.
    1225Se pasa una tabla de states con dos estados únicos, menuOpen y menuClosed. Cada estado contiene una transición para declarar (a través de un TweenInfo) cómo el estado particular alcanzará sus propiedades objetivo definidas en la tabla de properties. En este caso, menuOpen declara un cambio de estado a 45° para el Rotation del botón con un tween Exponential de ½ segundo, mientras que menuClosed efectivamente restaura el botón a su rotación por defecto de 0.
    26El estado inicial del botón se establece en menuClosed (esto podría establecerse en cualquier nombre de estado dentro de la tabla states).

    Más abajo en el script (líneas 76-86), los botones se conectan a la interacción del jugador para activar cambios en el estado de la UI:

    FilasPropósito
    7682SettingsButton se conecta al evento Activated de la clase GuiButton para llamar a una función anónima. Dentro de la función anónima, las líneas 7779 alternan una variable targetState entre menuOpen y menuClosed. La línea 80 llama a setState() para establecer el estado del botón en targetState y la línea `81 hace lo mismo para SettingsMenu para que se abra o cierre alternando con la activación de SettingsButton.
    8386CloseButton se conecta al evento Activated para llamar a una función anónima que establece el estado de ambos SettingsButton y SettingsMenu en menuClosed.

    Las líneas 30-49 inicializan y adjuntan comportamiento al menú de configuración de la siguiente manera:

    FilasPropósito
    3031Se declara una referencia local settingsMenu e se hidrata con la función StatefulObjectController.hydrate() y se referencia el marco SettingsMenu dentro de HUDContainer como el objeto a hidratar.
    3246De manera similar al botón de configuración, se pasa una tabla de states con dos estados únicos, menuOpen y menuClosed. Aquí, menuOpen declara un cambio de estado a UDim2.fromScale(0.5, 0.5) para la Position del marco con un tween de Bounce de ½ segundo, así como un estado de Visible true. Por el contrario, menuClosed declara un cambio de estado de posición a UDim2.fromScale(0.5, 0.4) y Visible a false, pero el TweenInfo con duración 0 en la línea 41 efectivamente hace que el cambio de estado ocurra de inmediato.
    48El estado inicial del marco se establece en menuClosed.

    Más abajo en el script (líneas 76-86), el menú de configuración está vinculado a la interacción del jugador:

    FilasPropósito
    81Establece el mismo targetState para SettingsMenu para sincronizar con la activación de SettingsButton.
    85Establece el estado de SettingsMenu en menuClosed cuando se activa CloseButton.

    Las líneas 51-73 inicializan y adjuntan comportamiento a EffectsVolumeSlider y BackgroundVolumeSlider de la siguiente manera:

    FilasPropósito
    52Establece una referencia local al Effects SoundGroup dentro de SoundService. Un SoundGroup te permite interrelacionar múltiples Sounds y controlar el volumen de cada sonido en el grupo a través de la propiedad Volume del grupo.
    5354Se declara una referencia local effectsVolumeSlider y se hidrata con la función SliderController.hydrate() y se referencia el marco EffectsVolumeSlider dentro de HUDContainer ⟩ SettingsMenu como el objeto a hidratar. Ten en cuenta que el segundo parámetro de true para FindFirstChild() le dice al método que busque recursivamente hacia abajo en la rama HUDContainer para localizar EffectsVolumeSlider.
    55El valor inicial del deslizador se establece al Volume actual del grupo Effects, o 0.5 como valor de respaldo.
    5660Establece la función de callback para aplicar los cambios de valor del deslizador al volumen del grupo de sonido Effects.
    6473Esencialmente lo mismo que las líneas 52-61, excepto para hidratar el marco BackgroundVolumeSlider dentro de HUDContainer ⟩ SettingsMenu y aplicar cambios de valor del deslizador al volumen del grupo de sonido Background.

Con SettingsScript en su lugar, la experiencia ahora ofrece un ejemplo completamente operativo de UI interactiva que vincula un conjunto relacionado de objetos de UI a la interacción del jugador.

©2026 Roblox Corporation. Roblox, el logotipo de Roblox y "Powering Imagination" son algunas de nuestras marcas registradas y no registradas en los Estados Unidos y otros países.