En animación, tweening es el proceso de generar fotogramas intermedios entre dos puntos clave en una secuencia. Al diseñar una interfaz de usuario, puedes usar tweening para transitar un GuiObject suavemente de un estado a otro, como:
- Aumentar suavemente el tamaño de un botón cuando un usuario lo selecciona.
- Deslizar menús de UI dentro y fuera de los bordes de la pantalla.
- Animar gradualmente una barra de salud entre dos anchos cuando un usuario recibe un aumento de salud.
Tweens de propiedad única
Posición
Para tweenear la posición de un GuiObject:
- Establece el AnchorPoint para el objeto.
- Pasa un TweenInfo y la posición objetivo a TweenService:Create().
- Reproduce el tween con Tween:Play().
El siguiente fragmento de código mueve un ImageLabel dentro de un ScreenGui al centro exacto de la pantalla:
local TweenService = game:GetService("TweenService")
local Players = game:GetService("Players")
local PlayerGui = Players.LocalPlayer:WaitForChild("PlayerGui")
local ScreenGui = PlayerGui:WaitForChild("ScreenGui")
local object = ScreenGui:WaitForChild("ImageLabel")
object.AnchorPoint = Vector2.new(0.5, 0.5)
local targetPosition = UDim2.new(0.5, 0, 0.5, 0)
local tweenInfo = TweenInfo.new(2)
local tween = TweenService:Create(object, tweenInfo, {Position = targetPosition})
tween:Play()Tamaño
Para tweenear el tamaño de un GuiObject:
- Adjunta un UIAspectRatioConstraint al objeto para mantener su relación de aspecto diseñada al tweenear.
- Pasa un TweenInfo y el tamaño objetivo a TweenService:Create().
- Reproduce el tween con Tween:Play().
El siguiente fragmento de código escala un ImageLabel dentro de un ScreenGui al 40% del ancho o alto de la pantalla (el que sea más pequeño) desde el punto de anclaje central del objeto:
local TweenService = game:GetService("TweenService")
local Players = game:GetService("Players")
local PlayerGui = Players.LocalPlayer:WaitForChild("PlayerGui")
local ScreenGui = PlayerGui:WaitForChild("ScreenGui")
local object = ScreenGui:WaitForChild("ImageLabel")
object.AnchorPoint = Vector2.new(0.5, 0.5)
local aspectRatioConstraint = Instance.new("UIAspectRatioConstraint")
aspectRatioConstraint.Parent = object
local targetSize = UDim2.new(0.4, 0, 0.4, 0)
local tweenInfo = TweenInfo.new(2)
local tween = TweenService:Create(object, tweenInfo, {Size = targetSize})
tween:Play()Rotación
Para tweenear la rotación de un GuiObject:
- Establece el AnchorPoint para el objeto alrededor del cual rotar.
- Determina la Rotación objetivo para el objeto.
- Pasa un TweenInfo y la rotación objetivo a TweenService:Create().
- Reproduce el tween con Tween:Play().
local TweenService = game:GetService("TweenService")
local Players = game:GetService("Players")
local PlayerGui = Players.LocalPlayer:WaitForChild("PlayerGui")
local ScreenGui = PlayerGui:WaitForChild("ScreenGui")
local object = ScreenGui:WaitForChild("ImageLabel")
object.AnchorPoint = Vector2.new(0.5, 0.5)
local targetRotation = 45
local tweenInfo = TweenInfo.new(2)
local tween = TweenService:Create(object, tweenInfo, {Rotation = targetRotation})
tween:Play()Transparencia
Múltiples propiedades controlan la transparencia de la UI, dependiendo del tipo de objeto. Puedes tweenear cada una de estas propiedades individualmente o combinadas a través de un tween de múltiples propiedades. Alternativamente, puedes tweenear la transparencia general de un objeto colocándolo dentro de un CanvasGroup y tweenando la GroupTransparency del grupo.
local TweenService = game:GetService("TweenService")
local Players = game:GetService("Players")
local PlayerGui = Players.LocalPlayer:WaitForChild("PlayerGui")
local ScreenGui = PlayerGui:WaitForChild("ScreenGui")
local object = ScreenGui:WaitForChild("ImageLabel")
local targetTransparency = 0.8
local tweenInfo = TweenInfo.new(2)
local tween = TweenService:Create(object, tweenInfo, {ImageTransparency = targetTransparency})
tween:Play()local TweenService = game:GetService("TweenService")
local Players = game:GetService("Players")
local PlayerGui = Players.LocalPlayer:WaitForChild("PlayerGui")
local ScreenGui = PlayerGui:WaitForChild("ScreenGui")
local canvasGroup = ScreenGui:WaitForChild("CanvasGroup")
local targetTransparency = 0.8
local tweenInfo = TweenInfo.new(2)
local tween = TweenService:Create(canvasGroup, tweenInfo, {GroupTransparency = targetTransparency})
tween:Play()Color
Múltiples propiedades controlan el color de la UI, dependiendo del tipo de objeto. Puedes tweenear cada una de estas propiedades individualmente o combinadas a través de un tween de múltiples propiedades. Alternativamente, puedes tweenear el color general de un objeto colocándolo dentro de un CanvasGroup y tweenando el GroupColor3 del grupo.
local TweenService = game:GetService("TweenService")
local Players = game:GetService("Players")
local PlayerGui = Players.LocalPlayer:WaitForChild("PlayerGui")
local ScreenGui = PlayerGui:WaitForChild("ScreenGui")
local object = ScreenGui:WaitForChild("ImageLabel")
local targetColor = Color3.fromRGB(255, 0, 0)
local tweenInfo = TweenInfo.new(2)
local tween = TweenService:Create(object, tweenInfo, {ImageColor3 = targetColor})
tween:Play()local TweenService = game:GetService("TweenService")
local Players = game:GetService("Players")
local PlayerGui = Players.LocalPlayer:WaitForChild("PlayerGui")
local ScreenGui = PlayerGui:WaitForChild("ScreenGui")
local canvasGroup = ScreenGui:WaitForChild("CanvasGroup")
local targetColor = Color3.fromRGB(255, 0, 0)
local tweenInfo = TweenInfo.new(2)
local tween = TweenService:Create(canvasGroup, tweenInfo, {GroupColor3 = targetColor})
tween:Play()Trazo
Múltiples propiedades controlan los bordes de la UI, dependiendo del tipo de objeto.
Alternativamente, puedes aplicar un hijo UIStroke y tweenear su grosor, color y/o transparencia.
| Objeto UI | Propiedades |
|---|---|
| UIStroke | Color, Thickness, Transparency |
local TweenService = game:GetService("TweenService")
local Players = game:GetService("Players")
local PlayerGui = Players.LocalPlayer:WaitForChild("PlayerGui")
local ScreenGui = PlayerGui:WaitForChild("ScreenGui")
local object = ScreenGui:WaitForChild("TextLabel")
local stroke = Instance.new("UIStroke")
stroke.Color = Color3.fromRGB(255, 255, 255)
stroke.Thickness = 5
stroke.Parent = object
local targetColor = Color3.fromRGB(255, 0, 0)
local targetThickness = 10
local tweenInfo = TweenInfo.new(2)
local tween = TweenService:Create(stroke, tweenInfo, {Color = targetColor, Thickness = targetThickness})
tween:Play()Tweens de múltiples propiedades
Puedes combinar cualquiera de los tweens de propiedad única en tweens más complejos pasando múltiples propiedades objetivo a TweenService:Create(), por ejemplo posición + rotación o tamaño + transparencia.
local TweenService = game:GetService("TweenService")
local Players = game:GetService("Players")
local PlayerGui = Players.LocalPlayer:WaitForChild("PlayerGui")
local ScreenGui = PlayerGui:WaitForChild("ScreenGui")
local object = ScreenGui:WaitForChild("ImageLabel")
object.AnchorPoint = Vector2.new(0.5, 0.5)
local targetPosition = UDim2.new(0.5, 0, 0.5, 0)
local targetRotation = 45
local tweenInfo = TweenInfo.new(2)
local tween = TweenService:Create(object, tweenInfo, {Position = targetPosition, Rotation = targetRotation})
tween:Play()local TweenService = game:GetService("TweenService")
local Players = game:GetService("Players")
local PlayerGui = Players.LocalPlayer:WaitForChild("PlayerGui")
local ScreenGui = PlayerGui:WaitForChild("ScreenGui")
local object = ScreenGui:WaitForChild("ImageLabel")
object.AnchorPoint = Vector2.new(0.5, 0.5)
local aspectRatioConstraint = Instance.new("UIAspectRatioConstraint")
aspectRatioConstraint.Parent = object
local targetSize = UDim2.new(0.4, 0, 0.4, 0)
local targetTransparency = 0.8
local tweenInfo = TweenInfo.new(2)
local tween = TweenService:Create(object, tweenInfo, {Size = targetSize, ImageTransparency = targetTransparency})
tween:Play()Secuencias de Tween
Puedes encadenar animaciones de UI para que ocurran una tras otra reproduciendo tweens subsiguientes al evento Completed del tween anterior. Por ejemplo, el siguiente script mueve un objeto al centro de la pantalla, luego lo rota 45°.
local TweenService = game:GetService("TweenService")
local Players = game:GetService("Players")
local PlayerGui = Players.LocalPlayer:WaitForChild("PlayerGui")
local ScreenGui = PlayerGui:WaitForChild("ScreenGui")
local object = ScreenGui:WaitForChild("ImageLabel")
object.AnchorPoint = Vector2.new(0.5, 0.5)
local targetPosition = UDim2.new(0.5, 0, 0.5, 0)
local targetRotation = 45
local tweenInfo = TweenInfo.new(2)
local positionTween = TweenService:Create(object, tweenInfo, {Position = targetPosition})
local rotationTween = TweenService:Create(object, tweenInfo, {Rotation = targetRotation})
-- Reproduce inicialmente el tween de posición
positionTween:Play()
-- Reproduce el tween de rotación al completar el tween de posición
positionTween.Completed:Connect(function()
rotationTween:Play()
end)Transiciones de estilo
Los objetos de UI también pueden ser animados a través de transiciones de estilo, comparables a transiciones CSS, donde una o más propiedades de UI son tweened a través de definiciones de StyleRule. Consulta la guía del Editor de Estilos para más detalles.

Opciones de easing
Usando las opciones de easing de TweenInfo, puedes controlar el estilo y la dirección del easing de las animaciones de UI.
Estilo
Enum.EasingStyle establece la tasa de interpolación de inicio a fin. Por defecto, el estilo de easing está configurado en Enum.EasingStyle.Quad.
| Estilo | Descripción |
|---|---|
| Lineal | Se mueve a una velocidad constante. |
| Seno | La velocidad está determinada por una onda seno para un movimiento de easing suave. |
| Cuadrático | Similar a Seno pero con una curva ligeramente más pronunciada basada en la interpolación cuadrática. |
| Cúbico | Similar a Cuadrático pero con una curva ligeramente más pronunciada basada en la interpolación cúbica. |
| Cuártico | Similar a Cúbico pero con una curva aún más pronunciada basada en la interpolación cuártica. |
| Quintico | Similar a Cuártico pero con una curva aún más pronunciada basada en la interpolación quintica. |
| Exponencial | La curva más pronunciada basada en la interpolación exponencial. |
| Circular | Sigue un arco circular, de modo que la aceleración es más repentina y la desaceleración más gradual en comparación con Quintico o Exponencial. |
| Retroceso | Sobrepasa ligeramente el objetivo, luego retrocede a su lugar. |
| Rebote | Rebota hacia atrás varias veces después de alcanzar el objetivo, antes de finalmente asentarse. |
| Elástico | Se mueve como si estuviera unido a una banda elástica, sobrepasando el objetivo varias veces. |

local tweenInfo = TweenInfo.new(2, Enum.EasingStyle.Cubic)
local tween = TweenService:Create(object, tweenInfo, {Rotation = 45})Dirección
Enum.EasingDirection define cómo se aplica la interpolación del estilo de easing a un objeto, con un valor por defecto de Out. Ten en cuenta que un tween con estilo de easing Lineal no se ve afectado, ya que la interpolación lineal es constante de inicio a fin.
| Dirección | Descripción |
|---|---|
| In | El estilo de easing se aplica en dirección hacia adelante. |
| Out | El estilo de easing se aplica en dirección inversa. |
| InOut | El estilo de easing se aplica hacia adelante en la primera mitad y en reversa en la segunda mitad. |
local tweenInfo = TweenInfo.new(2, Enum.EasingStyle.Cubic, Enum.EasingDirection.InOut)
local tween = TweenService:Create(object, tweenInfo, {Rotation = 45})Efecto de máquina de escribir en texto
Puedes mejorar fácilmente la UI basada en texto, como banners de escenas, instrucciones para jugadores y mensajes, con efectos animados. El efecto "máquina de escribir" es ideal para TextLabels que cuentan una historia, muestran conversaciones de NPC, etc.
Crea un nuevo ModuleScript dentro de ReplicatedStorage.
Renombra el nuevo script a AnimateUI.

Pega el siguiente código en el script:
ModuleScript - AnimateUIlocal LocalizationService = game:GetService("LocalizationService")local Players = game:GetService("Players")local SOURCE_LOCALE = "en"local translator = nillocal AnimateUI = {}function AnimateUI.loadTranslator()pcall(function()translator = LocalizationService:GetTranslatorForPlayerAsync(Players.LocalPlayer)end)if not translator thenpcall(function()translator = LocalizationService:GetTranslatorForLocaleAsync(SOURCE_LOCALE)end)endendfunction AnimateUI.typeWrite(guiObject, text, delayBetweenChars)guiObject.Visible = trueguiObject.AutoLocalize = falselocal displayText = text-- Traduce el texto si es posibleif translator thendisplayText = translator:Translate(guiObject, text)end-- Reemplaza las etiquetas de salto de línea para que el bucle de grafemas no se pierda esos caracteresdisplayText = displayText:gsub("<br%s*/>", "\n")-- Elimina las etiquetas RichText ya que la animación carácter por carácter romperá las etiquetasdisplayText = displayText:gsub("<[^<>]->", "")-- Establece el texto traducido/modificado en el padreguiObject.Text = displayTextlocal index = 0for first, last in utf8.graphemes(displayText) doindex += 1guiObject.MaxVisibleGraphemes = indextask.wait(delayBetweenChars)endendreturn AnimateUICrea un TextLabel en una ubicación adecuada, como dentro de un ScreenGui parentado a StarterGui.
Inserta un nuevo LocalScript como un hijo directo de la etiqueta y pega el siguiente código. Ten en cuenta que cada mensaje se muestra llamando a AnimateUI.typeWrite() con parámetros para el objeto padre, la cadena a mostrar y el retraso entre caracteres.
LocalScriptlocal ReplicatedStorage = game:GetService("ReplicatedStorage")local AnimateUI = require(ReplicatedStorage:WaitForChild("AnimateUI"))local label = script.Parent-- Carga el traductor si el juego está localizado--AnimateUI.loadTranslator()local message1 = [[Más allá de esta puerta está el<br /><font size="46" color="rgb(255,50,25)">Gran Zorgoth...</font> <font size="40">🗡</font>]]AnimateUI.typeWrite(label, message1, 0.05)task.wait(1)local message2 = [[...quien gobierna esta mazmorras <font color="rgb(255,200,50)">sin ser desafiado!</font> <font size="30">😈</font>]]AnimateUI.typeWrite(label, message2, 0.05)