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 juego comúnmente muestra elementos de UI no interactivos, como el medidor de salud demostrado en Crear medidores HUD. Además de esto, casi todos los juegos requieren UI interactiva como botones que responden a la activación del jugador, animan cuando se activan, hacen tween de menús con otros controles interactivos, etc.

Vista en el 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 punto de partida y Fundamentos de UI - Interactividad como referencia final, este tutorial demuestra:

  • Cómo posicionar 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 arrastrables.
  • Uso de un ModuleScripts para formar módulos de "controlador" para el 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 arrastrables 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 vista 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 máximo espacio 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 interactivos con funcionalidad incorporada, 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 en forma de "engranaje" para alternar el menú de configuración abierto o cerrado.

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 (relación de aspecto 1:1).

    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 en 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 final 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 la configuración o a otra información bajo demanda. En este tutorial, el menú contendrá deslizadores interactivos para ajustar los niveles de volumen del audio de fondo y de los efectos de sonido de forma independiente.

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

Crear el marco padre

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 padre, 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 en 2.5. (2.5:1 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 en 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 en 800, inf y su MinSize en 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 arrastrables impulsados por UIDragDetector, un objeto conveniente que facilita la interacción con elementos de interfaz de usuario 2D.


Para crear un contenedor padre 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 (ancla central)

    • 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% del 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 flex.

    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 elementos de izquierda a derecha)
    • HorizontalFlex = Fill (redimensionar elementos horizontalmente para llenar todo el contenedor padre, sobrescribiendo 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 el propósito del deslizador cuando abren el menú de configuración.

Icono que indica el propósito 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 del juego 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 ancho a alto).

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

Marco de rango

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

Tamaño y posición objetivo de la porción interactiva del deslizador.
  1. Inserta un nuevo Frame en el marco EffectsVolumeSlider y renómbralo SliderFrame. Nota 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 del deslizador 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 del 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 (ancla central)
    • 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 del mango visualmente frente a 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 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 vuelta en la ventana Explorador, haz clic en el padre SliderFrame del mango.
    Diagrama que muestra el proceso de vinculación de la propiedad BoundingUI del detector al contenedor SliderFrame.

    La propiedad BoundingUI ahora refleja el contenedor SliderFrame:

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

Si pruebas el juego 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 agregar 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 frente al relleno/contorno del marco padre)
  3. Para coincidir con la forma de "pastilla" 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 otro propósito, 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 completado seleccionado.
  2. Duplicalo (CtrlD o D) y luego renombra el duplicado a BackgroundVolumeSlider.

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

    BackgroundVolumeSlider posicionado debajo de 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 imagen de 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 imagen de 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 color InnerFill modificado.

Crear el botón de cerrar

El último elemento 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 servirá para el mismo propósito).

Menú de configuración con 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. ImageButton 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 inserción 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 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

Una configuración 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 al permitirte reutilizar código entre scripts en diferentes lados de la frontera cliente-servidor o en el mismo lado de la frontera.

Controlador de objeto con estado

El siguiente módulo controlador de objeto con estado te permite adjuntar comportamiento a objetos de UI como SettingsButton y SettingsMenu, y alternar/tween 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 reutilizar y 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("Se intentó establecer %s en 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
    LinesPropósito
    610Define y exporta los tipos de Luau para mejorar la autocompletación y el linting 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 de 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 en el 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 de 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 el juego.

  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("Se intentó hidratar el deslizador %s pero no se pudo encontrar el Handle", object:GetFullName()))
    end
    local innerFill = object:FindFirstChild("InnerFill", true)
    if not innerFill then
    warn(string.format("Se intentó hidratar el deslizador %s pero no se pudo encontrar el InnerFill", object:GetFullName()))
    end
    local dragDetector = handle:FindFirstChildWhichIsA("UIDragDetector")
    if not dragDetector then
    warn(string.format("Se intentó hidratar el deslizador %s pero no se pudo encontrar el 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 detector a la manipulación 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 interno para que coincidan
    self.handle.Position = UDim2.fromScale(clampedValue, 0.5)
    self.innerFill.Size = UDim2.fromScale(clampedValue, 1)
    -- Ejecutar la callback del usuario con el último valor
    local changeSuccess, changeResult = pcall(self.onChanged, clampedValue)
    if not changeSuccess then
    warn("Error en la callback del deslizador:", changeResult)
    end
    end
    return SliderController
    LinesPropó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 los elementos mango, relleno interno y UIDragDetector del deslizador. La línea 38 llama a la función setValue() del módulo y las líneas 4143 conectan el evento DragContinue del detector de arrastre 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 según sea necesario.

Crear el script de configuración

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

  1. Inserta un nuevo LocalScript en HUDContainer y renómbralo a SettingsScript para describir su propósito. Nota 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:

    LinesPropósito
    1011Se declara una referencia local settingsButton y se hidrata con la función StatefulObjectController.hydrate(), y se referencia el botón SettingsButton dentro de HUDContainer como el objeto a hidratar.
    1225Se pasa una tabla 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 properties. En este caso, menuOpen declara un cambio de estado a 45° para la Rotation del botón con un tween de Exponential de ½ segundo, mientras que menuClosed efectivamente restaura el botón a su rotación predeterminada 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 adelante 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:

    LinesPropósito
    7682SettingsButton está conectado 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 luego 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 con la activación de SettingsButton.
    8386CloseButton está conectado 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:

    LinesPropósito
    3031Se declara una referencia local settingsMenu y se hidrata con la función StatefulObjectController.hydrate() y se referencia el marco SettingsMenu dentro de HUDContainer como el objeto a hidratar.
    3246Similar al botón de configuración, se pasa una tabla 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 de true. En contraste, menuClosed declara un cambio de estado posicional 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 instantáneamente.
    48El estado inicial del marco se establece en menuClosed.

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

    LinesPropósito
    81Establece el mismo targetState para SettingsMenu para sincronizarlo 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:

    LinesPropósito
    52Establece una referencia local al SoundGroup Effects 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. Nota 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 en el Volume actual del grupo de sonido Effects, o 0.5 como respaldo.
    5660Establece la función de callback para aplicar cambios en el 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 en el valor del deslizador al volumen del grupo de sonido Background.

Con SettingsScript en su lugar, el juego ahora ofrece un ejemplo de UI interactiva completamente operativo 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.