
Por Qué Aprender Luau Scripting
Ya sabes cómo colocar parts y construir cosas en Roblox Studio. Eso te da un mundo estático – paredes, pisos, decoraciones. Pero en el momento en que quieres una puerta que se abra, un leaderboard que rastree puntos, o enemigos que persigan jugadores, necesitas scripts. Y los scripts en Roblox se escriben en Luau.
Luau es el lenguaje de programación de Roblox. Está basado en Lua 5.1, pero Roblox agregó verificación de tipos, optimizaciones de rendimiento y un montón de APIs integradas que se comunican directamente con el game engine. Si ya pasaste por nuestro tutorial de Roblox Studio para principiantes, este es tu siguiente paso. Vamos de construir a programar.
¿La mejor parte? Luau fue literalmente diseñado para personas que nunca han programado. La sintaxis es limpia, los mensajes de error son legibles, y puedes ver los resultados de tu código en tiempo real presionando F5. Sin compilar, sin terminal, sin configuración complicada. Solo escribe código y mira tu juego reaccionar.
Vamos a empezar.
Configurando Tu Primer Script en Roblox Studio
Antes de escribir cualquier código, necesitas entender dónde van los scripts en Roblox Studio. Esto importa más de lo que piensas – poner un script en el lugar equivocado es la razón número uno por la que los principiantes se confunden cuando su código no hace nada.
Tipos de Script y Dónde Van
| Tipo de Script | Ubicación | Propósito |
|---|---|---|
| Script | ServerScriptService | Lógica de juego que corre en el servidor (daño, puntuación, guardar datos) |
| LocalScript | StarterPlayerScripts o StarterGui | Código del lado del jugador (cámara, UI, input) |
| ModuleScript | ReplicatedStorage o ServerStorage | Código reutilizable que otros scripts pueden usar con require |
Para este tutorial, vamos a empezar con Scripts regulares en ServerScriptService. Estos corren en el servidor y afectan a todos los jugadores por igual.
Creando Tu Primer Script
- Abre Roblox Studio y carga cualquier proyecto (un Baseplate funciona)
- En el panel Explorer, encuentra ServerScriptService
- Haz clic derecho y selecciona Insert Object > Script
- El editor de script se abre con una sola línea:
print("Hello world!") - Presiona F5 para probar
- Revisa la ventana Output (View > Output si no la ves)
Deberías ver “Hello world!” impreso en el Output. Esa sola línea corrió en el servidor de Roblox. Todo a partir de aquí se construye sobre este mismo flujo de trabajo: escribe código, presiona F5, revisa el Output.
Si no ves la ventana Output, ve a View en el menú superior y haz clic en Output. Vas a usar esta ventana constantemente, así que mantenla abierta.
Variables y Tipos de Datos en Luau
Las variables almacenan información que tus scripts usan. Piensa en ellas como cajas con etiquetas – pones un valor adentro y referencias la etiqueta cada vez que necesitas ese valor.
Declarando Variables
En Luau, creas variables con la palabra clave local:
local playerName = "RobloxDrop"
local maxHealth = 100
local isGameOver = false
local speedMultiplier = 1.5
Siempre usa local. Técnicamente Luau te permite omitirlo, pero eso crea variables globales que causan bugs en proyectos más grandes y corren más lento. Haz de local un hábito desde el primer día.
Tipos de Datos Que Vas a Usar
| Tipo | Ejemplo | Caso de Uso |
|---|---|---|
| string | "Hello" | Nombres de jugadores, mensajes, texto de UI |
| number | 42, 3.14 | Vida, velocidad, puntajes, posiciones |
| boolean | true, false | Toggles, condiciones, estado del juego |
| nil | nil | Nada, vacío, aún no definido |
| table | {1, 2, 3} | Listas, inventarios, datos de leaderboard |
Operaciones con Strings
Las strings son valores de texto y las vas a usar en todas partes:
local firstName = "Roblox"
local lastName = "Drop"
-- Concatenación (unir strings)
local fullName = firstName.. lastName -- "RobloxDrop"
local spaced = firstName.. " ".. lastName -- "Roblox Drop"
-- Longitud de string
local nameLength = #fullName -- 10
-- Funciones útiles de string
local upper = string.upper(fullName) -- "ROBLOXDROP"
local lower = string.lower(fullName) -- "robloxdrop"
local sub = string.sub(fullName, 1, 6) -- "Roblox"
Tables (Arrays y Diccionarios)
Las tables son la estructura de datos multipropósito de Luau. Funcionan tanto como listas ordenadas como pares clave-valor:
-- Array (lista ordenada)
local fruits = {"Apple", "Banana", "Cherry"}
print(fruits[1]) -- "Apple" (los arrays en Luau empiezan en 1, no en 0)
-- Diccionario (pares clave-valor)
local playerStats = {
health = 100,
speed = 16,
level = 1
}
print(playerStats.health) -- 100
-- Agregando a una table
table.insert(fruits, "Mango")
playerStats.coins = 50
Las tables se volverán esenciales cuando construyas inventarios, guardes datos de jugadores o almacenes configuraciones del juego.
Funciones: Bloques Reutilizables de Lógica
Las funciones te permiten empaquetar código en bloques reutilizables. En vez de escribir la misma lógica una y otra vez, la defines una vez y la llamas cada vez que la necesites.
Definiendo y Llamando Funciones
local function healPlayer(humanoid, amount)
local newHealth = humanoid.Health + amount
if newHealth > humanoid.MaxHealth then
newHealth = humanoid.MaxHealth
end
humanoid.Health = newHealth
print("Healed to ".. newHealth)
end
Esa función recibe un objeto Humanoid y una cantidad de curación, limita la vida al máximo y aplica la curación. La llamas así:
-- En otro lugar de tu código
healPlayer(someHumanoid, 25)
Funciones Que Retornan Valores
Las funciones también pueden calcular algo y devolver el resultado:
local function calculateDamage(baseDamage, level)
local multiplier = 1 + (level * 0.1)
return baseDamage * multiplier
end
local damage = calculateDamage(50, 10)
print(damage) -- 100
Funciones Anónimas
Vas a ver funciones sin nombre todo el tiempo en Roblox scripting, especialmente con eventos:
part.Touched:Connect(function(hit)
print(hit.Name.. " touched the part")
end)
Ese bloque function(hit) ... end es una función anónima – no tiene nombre, simplemente corre cuando el evento se dispara. Este patrón está en todas partes en Luau.
Eventos y Conexiones: Haciendo Que las Cosas Pasen
Los eventos son el latido de cualquier juego de Roblox. Se disparan cuando algo sucede – un jugador toca una part, un personaje aparece, un valor cambia. Tus scripts escuchan eventos y responden a ellos.
Cómo Funcionan los Eventos
Cada objeto de Roblox tiene eventos a los que puedes conectarte. El patrón siempre es el mismo:
object.EventName:Connect(function(parameters)
-- Tu código corre aquí cuando el evento se dispara
end)
Eventos Comunes Que Vas a Usar
| Evento | Se Dispara Cuando | Se Encuentra En |
|---|---|---|
Touched | Algo toca físicamente la part | BasePart |
TouchEnded | Algo deja de tocar la part | BasePart |
PlayerAdded | Un nuevo jugador se une al servidor | Players service |
PlayerRemoving | Un jugador sale del servidor | Players service |
CharacterAdded | El personaje de un jugador aparece o reaparece | Player object |
Changed | El valor de una propiedad cambia | Cualquier instance |
ChildAdded | Un nuevo child se agrega a un objeto | Cualquier instance |
Conectando a PlayerAdded
Uno de los eventos más importantes. Se dispara cada vez que un jugador se une a tu juego:
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player)
print(player.Name.. " joined the game!")
end)
La línea game:GetService("Players") es cómo accedes a los services de Roblox. Los services son objetos de nivel superior que manejan diferentes sistemas – Players maneja las conexiones de jugadores, Lighting maneja el ambiente, DataStoreService maneja el guardado de datos, y así sucesivamente.
Desconectando Eventos
A veces necesitas que un evento se dispare solo una vez o deje de escuchar:
local connection
connection = part.Touched:Connect(function(hit)
print("Touched once!")
connection:Disconnect -- Deja de escuchar después del primer toque
end)
Esto es útil para activadores de una sola vez como recoger un coleccionable o abrir un cofre.
Haciendo un Script de Puerta Funcional
Vamos a construir algo práctico. Una puerta que se abre cuando un jugador la toca y se cierra después de unos segundos. Esto combina variables, funciones, eventos y temporización – todo lo que hemos cubierto hasta ahora.
Paso 1: Configura la Puerta
- Crea una Part en tu workspace
- Redimensiónala para que parezca una puerta (prueba con Size 1, 7, 5)
- Píntala de marrón y establece Material como Wood
- Ánclala (esto es crítico)
- Nómbrala “Door” en el panel Properties
Paso 2: Escribe el Script
Haz clic derecho en la part Door en el Explorer, inserta un Script y reemplaza el código por defecto:
local door = script.Parent
local debounce = false
local openTime = 3
local closedPosition = door.Position
local openOffset = Vector3.new(0, door.Size.Y, 0)
local function openDoor
if debounce then return end
debounce = true
-- Mueve la puerta hacia arriba (abre)
door.Position = closedPosition + openOffset
door.Transparency = 0.5
door.CanCollide = false
print("Door opened")
task.wait(openTime)
-- Mueve la puerta de vuelta abajo (cierra)
door.Position = closedPosition
door.Transparency = 0
door.CanCollide = true
print("Door closed")
debounce = false
end
door.Touched:Connect(function(hit)
local humanoid = hit.Parent:FindFirstChild("Humanoid")
if humanoid then
openDoor
end
end)
Cómo Funciona
- debounce impide que la puerta se active repetidamente mientras ya está abierta. Este es un patrón que vas a usar en casi todo script interactivo.
- task.wait(3) pausa el script por 3 segundos antes de cerrar la puerta. La biblioteca
taskes la forma moderna de manejar temporización en Luau. - Verificamos si hay un Humanoid en el objeto que tocó para asegurarnos de que solo los jugadores (no parts aleatorias) activen la puerta.
- La puerta se mueve hacia arriba por su propia altura, se vuelve semi-transparente y desactiva la colisión para que los jugadores puedan pasar.
Presiona F5 y camina hacia la puerta. Debería deslizarse hacia arriba, quedarse abierta por 3 segundos y volver a bajar. Si estás construyendo etapas de obby, dungeons de RPG o puertas de tycoon, este patrón de puerta es tu base.
Construyendo un Leaderboard de Puntos
Los leaderboards permiten a los jugadores ver sus estadísticas en el lado derecho de la pantalla. Roblox tiene un sistema de leaderboard integrado vinculado a una folder llamada “leaderstats.” Una vez que lo configuras, el leaderboard aparece automáticamente – no se necesita scripting de UI.
El Script del Leaderboard
Crea un nuevo Script en ServerScriptService y agrega este código:
local Players = game:GetService("Players")
local function onPlayerAdded(player)
-- Crea la folder leaderstats
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
-- Crea un valor de Points
local points = Instance.new("IntValue")
points.Name = "Points"
points.Value = 0
points.Parent = leaderstats
-- Crea un valor de Level
local level = Instance.new("IntValue")
level.Name = "Level"
level.Value = 1
level.Parent = leaderstats
print(player.Name.. " leaderstats created")
end
Players.PlayerAdded:Connect(onPlayerAdded)
Presiona F5 y verás un leaderboard aparecer en la esquina superior derecha con tu nombre de usuario, 0 Points y Level 1.
Agregando un Pickup de Puntos
Ahora vamos a crear parts que dan puntos cuando un jugador las toca. Agrega esto a un nuevo Script dentro de ServerScriptService:
local function setupCoin(coin)
coin.Touched:Connect(function(hit)
local humanoid = hit.Parent:FindFirstChild("Humanoid")
if not humanoid then return end
local player = game:GetService("Players"):GetPlayerFromCharacter(hit.Parent)
if not player then return end
local points = player:FindFirstChild("leaderstats")
and player.leaderstats:FindFirstChild("Points")
if not points then return end
points.Value = points.Value + 10
coin:Destroy
print(player.Name.. " collected a coin! Total: " .. points.Value)
end)
end
-- Configura todas las parts en una folder llamada "Coins"
local coinsFolder = workspace:FindFirstChild("Coins")
if coinsFolder then
for _, coin in coinsFolder:GetChildren do
setupCoin(coin)
end
end
Para que esto funcione, crea una Folder en Workspace llamada “Coins” y agrega algunas Parts pequeñas y amarillas dentro. Cada una se convierte en un coleccionable que agrega 10 puntos al leaderboard. Este es el mismo concepto detrás de la recolección de monedas en tycoons, obbies y juegos de aventura.
Si quieres aprender cómo convertir mecánicas de juego simples como esta en una experiencia publicada completa, nuestra guía sobre cómo hacer un juego popular en Roblox cubre el proceso de diseño y lanzamiento.
Tips de Debugging Que Te Van a Ahorrar Horas
Todo programador pasa tiempo haciendo debugging. La diferencia entre un principiante frustrado y un scripter productivo es saber cómo encontrar y corregir errores rápidamente.
Leyendo Mensajes de Error
Cuando un script se rompe, Roblox te dice exactamente qué salió mal en la ventana Output. Un error típico se ve así:
ServerScriptService.Script:15: attempt to index nil with 'Health'
Esto te dice:
- ServerScriptService.Script – Qué script tiene el error
- :15 – El número de línea (línea 15)
- attempt to index nil with ‘Health’ – Intentaste acceder a
.Healthen algo que no existe (nil)
Usando Print para Debugging
Cuando no estás seguro de qué está haciendo tu código, agrega comandos print para rastrear el flujo:
local function onTouched(hit)
print("1. Something touched the part:", hit.Name)
local humanoid = hit.Parent:FindFirstChild("Humanoid")
print("2. Found humanoid:", humanoid)
if humanoid then
print("3. Player health:", humanoid.Health)
humanoid.Health = humanoid.Health - 25
print("4. New health:", humanoid.Health)
end
end
Corre el juego y revisa el Output. Si ves que el paso 1 se imprime pero no el paso 2, sabes que el problema está entre esas líneas. Esta técnica de “print debugging” funciona en todos los niveles de habilidad.
Tipos Comunes de Error
| Error | Qué Significa | Corrección |
|---|---|---|
attempt to index nil | Estás accediendo a una propiedad en algo que no existe | Verifica si el objeto existe antes de usarlo con FindFirstChild |
Expected 'end' | Olvidaste cerrar una function, bloque if o loop | Cuenta tus aperturas de function/if/for y asegúrate de que cada una tenga un end |
Expected identifier | Error de escritura en una keyword o nombre de variable | Revisa la ortografía cuidadosamente, Luau distingue entre mayúsculas y minúsculas |
Infinite yield possible | WaitForChild está esperando algo que puede que nunca aparezca | Asegúrate de que el objeto que estás esperando realmente existe o se crea |
La Ventana Output Es Tu Mejor Amiga
Mantén la ventana Output abierta todo el tiempo. Ve a View > Output si no está visible. Cada error, cada print, cada advertencia aparece aquí. Ignorarla es como manejar con los ojos cerrados.
También puedes filtrar mensajes – haz clic derecho en la ventana Output para mostrar solo errores, advertencias o mensajes. Cuando tu juego se vuelve complejo y el Output está ruidoso, filtrar te ayuda a enfocarte.
Errores Comunes de Principiantes en Luau
Después de ayudar a cientos de nuevos scripters, estos son los errores que aparecen una y otra vez. Conocerlos de antemano te va a ahorrar frustración real.
1. Olvidar la Palabra Clave local
-- Mal: crea una variable global
playerScore = 100
-- Bien: crea una variable local
local playerScore = 100
Las variables globales se filtran entre scripts y causan bugs impredecibles. Siempre usa local.
2. Poner Scripts en el Service Equivocado
Un Script en StarterPlayerScripts no va a funcionar. Un LocalScript en ServerScriptService no va a funcionar. Combina el tipo de script con la ubicación correcta cada vez.
3. No Verificar Nil
-- Esto crashea si no hay Humanoid
hit.Parent.Humanoid.Health = 0
-- Esto es seguro
local humanoid = hit.Parent:FindFirstChild("Humanoid")
if humanoid then
humanoid.Health = 0
end
Siempre usa FindFirstChild antes de acceder a objetos hijos. No todo lo que toca una part es un personaje de jugador.
4. Olvidar Que Touched Se Dispara Para Cada Parte del Cuerpo
Cuando un jugador camina hacia una part, el evento Touched se dispara para la cabeza, torso y cada extremidad. Sin debounce, tu código corre 5+ veces:
local debounce = false
part.Touched:Connect(function(hit)
if debounce then return end
debounce = true
-- Tu código aquí (corre una vez)
task.wait(1)
debounce = false
end)
5. Usar wait en Vez de task.wait
La vieja función wait está deprecada. Siempre usa task.wait en su lugar:
-- Viejo (deprecado, menos preciso)
wait(2)
-- Nuevo (recomendado, más confiable)
task.wait(2)
La biblioteca task también te da task.spawn, task.delay y task.defer para más control sobre temporización.
6. Loops Infinitos Sin Yields
Si escribes un while loop que nunca se pausa, congela todo el juego:
-- Esto congela el juego
while true do
-- haciendo cosas por siempre sin pausa
end
-- Esto funciona bien
while true do
-- haciendo cosas
task.wait(1) -- Pausa 1 segundo cada loop
end
Cada loop necesita un task.wait o algún otro punto de yield. Sin excepciones.
Si te encuentras con problemas de rendimiento al probar tus scripts, revisa nuestra guía de corrección de lag y rendimiento en Roblox para técnicas de optimización.
Verificación de Tipos en Luau (Característica)
Una de las mayores ventajas de Luau sobre Lua estándar es su sistema de tipos. Las type annotations ayudan a detectar bugs antes de que siquiera corras tu juego.
Type Annotations Básicas
local playerName: string = "RobloxDrop"
local health: number = 100
local isAlive: boolean = true
local function calculateDamage(base: number, multiplier: number): number
return base * multiplier
end
No tienes que usar tipos – son opcionales. Pero agregarlos a los parámetros de funciones y valores de retorno ayuda a Studio a detectar errores en el editor antes de que presiones F5. Conforme tus scripts se hacen más largos, la verificación de tipos se vuelve increíblemente valiosa.
Habilitando el Modo Strict
Agrega este comentario al inicio de tu script para habilitar la verificación de tipos estricta:
--!strict
local function greet(name: string): string
return "Hello, " .. name
end
greet(42) -- Studio te advierte: number no es string
El modo strict detecta incompatibilidades de tipo, valores de retorno faltantes y otros problemas que de otra forma solo aparecerían en runtime. No es obligatorio para principiantes, pero vale la pena aprenderlo temprano.
Siguientes Pasos Después de Este Tutorial
Ahora tienes los fundamentos de Luau scripting – variables, funciones, eventos, ejemplos prácticos y habilidades de debugging. Aquí es hacia dónde ir para seguir subiendo de nivel tu desarrollo de juegos:
Temas Intermedios:
- RemoteEvents y RemoteFunctions – Comunicación entre scripts de servidor y cliente. Requerido para cualquier característica multiplayer como trading, sistemas de chat o mecánicas de equipo.
- DataStoreService – Guardar datos de jugadores (monedas, niveles, inventario) para que persistan entre sesiones. Sin esto, los jugadores pierden todo cuando se van.
- ModuleScripts – Organiza tu código en módulos reutilizables en vez de meter todo en un script enorme.
- TweenService – Animaciones suaves para mover parts, hacer fade en UI y crear efectos visuales pulidos sin scripting frame-by-frame.
Temas Avanzados:
- Metatables y OOP – Patrones orientados a objetos en Luau para construir sistemas complejos como clases de armas o IA de enemigos.
- Raycasting – Detectar hacia dónde un jugador está mirando o disparando. Esencial para juegos FPS y sistemas de interacción.
- CollectionService – Etiquetar objetos y manejar grupos de ítems similares de forma eficiente.
La documentación oficial Roblox Creator Documentation cubre cada API en detalle e incluye ejemplos interactivos. El DevForum en devforum.roblox.com es donde desarrolladores experimentados comparten tutoriales y responden preguntas.
Para inspiración sobre lo que puedes construir, navega por nuestro compilado de los mejores juegos de Roblox y haz ingeniería inversa de lo que hace funcionar a los juegos populares. Revisa las experiencias 4D generation de Roblox para ver hacia dónde va la plataforma y qué tipos de juegos están recibiendo atención del propio Roblox.
Explora todo nuestro contenido de desarrollo y estrategia en nuestro hub de guías – desde monetización hasta creación de UGC, hay una guía para cada paso de tu camino como creador en Roblox.
Tienes las herramientas. Tienes el conocimiento. Ahora ve a construir algo y hazlo tuyo.
FAQ
¿Luau es lo mismo que Lua?
Luau está basado en Lua 5.1, pero incluye adiciones específicas de Roblox como tipado estricto, type annotations y mejoras de rendimiento. La mayoría del código Lua estándar funciona en Luau, pero Luau tiene características extra que Lua estándar no tiene.
¿Necesito experiencia en programación antes de aprender Luau?
No. Luau está diseñado para ser amigable con principiantes y funciona como un primer lenguaje de programación. Si puedes seguir instrucciones paso a paso y estás dispuesto a experimentar, puedes aprender Luau.
¿Dónde pongo mis scripts en Roblox Studio?
Los scripts de servidor van en ServerScriptService. Los LocalScripts van en StarterPlayerScripts o StarterGui. Los ModuleScripts van en ReplicatedStorage o ServerStorage dependiendo de quién necesita accederlos.
¿Cuál es la diferencia entre Script y LocalScript?
Un Script corre en el servidor y controla la lógica compartida del juego. Un LocalScript corre en el dispositivo de un solo jugador y maneja cosas como el movimiento de cámara, UI y detección de input.
¿Cómo hago debug de scripts Luau?
Abre la ventana Output desde el menú View. Muestra comandos print y mensajes de error con números de línea. Agrega llamadas print a lo largo de tu código para rastrear el flujo de ejecución e identificar dónde las cosas se rompen.
¿Puedo construir un juego multiplayer completo con Luau?
Sí. Los juegos de Roblox son multiplayer por defecto. Los Scripts en el servidor manejan el estado compartido mientras que los LocalScripts manejan la experiencia de cada jugador. Los RemoteEvents conectan servidor y cliente.
¿Cuánto tiempo toma ser bueno en Luau?
Scripts básicos como puertas y kill bricks toman un día para aprender. Eventos y game loops toman alrededor de una semana. Guardar datos, remote events y sistemas de juego pulidos toman de 2 a 4 semanas de práctica consistente.
¿Cuáles son los errores más comunes de principiantes?
Olvidar la palabra clave local, poner scripts en el service equivocado, no verificar nil antes de acceder a propiedades y saltarse la ventana Output cuando ocurren errores.
¿Luau es lo suficientemente rápido para juegos complejos?
Sí. Luau fue específicamente optimizado por Roblox para rendimiento en juegos. Maneja física, IA, grandes cantidades de jugadores y sistemas complejos sin problemas cuando sigues buenas prácticas de programación.
¿Qué recursos debo usar para seguir aprendiendo?
Empieza con la documentación oficial Roblox Creator Docs en create.roblox.com/docs. Únete al DevForum para ayuda de la comunidad. Sigue a creadores de YouTube que se especializan en tutoriales de desarrollo para Roblox.
