Tutorial de Luau scripting en Roblox mostrando editor de código en Roblox Studio

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 ScriptUbicaciónPropósito
ScriptServerScriptServiceLógica de juego que corre en el servidor (daño, puntuación, guardar datos)
LocalScriptStarterPlayerScripts o StarterGuiCódigo del lado del jugador (cámara, UI, input)
ModuleScriptReplicatedStorage o ServerStorageCó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

  1. Abre Roblox Studio y carga cualquier proyecto (un Baseplate funciona)
  2. En el panel Explorer, encuentra ServerScriptService
  3. Haz clic derecho y selecciona Insert Object > Script
  4. El editor de script se abre con una sola línea: print("Hello world!")
  5. Presiona F5 para probar
  6. 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

TipoEjemploCaso de Uso
string"Hello"Nombres de jugadores, mensajes, texto de UI
number42, 3.14Vida, velocidad, puntajes, posiciones
booleantrue, falseToggles, condiciones, estado del juego
nilnilNada, 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

EventoSe Dispara CuandoSe Encuentra En
TouchedAlgo toca físicamente la partBasePart
TouchEndedAlgo deja de tocar la partBasePart
PlayerAddedUn nuevo jugador se une al servidorPlayers service
PlayerRemovingUn jugador sale del servidorPlayers service
CharacterAddedEl personaje de un jugador aparece o reaparecePlayer object
ChangedEl valor de una propiedad cambiaCualquier instance
ChildAddedUn nuevo child se agrega a un objetoCualquier 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

  1. Crea una Part en tu workspace
  2. Redimensiónala para que parezca una puerta (prueba con Size 1, 7, 5)
  3. Píntala de marrón y establece Material como Wood
  4. Ánclala (esto es crítico)
  5. 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 task es 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 .Health en 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

ErrorQué SignificaCorrección
attempt to index nilEstás accediendo a una propiedad en algo que no existeVerifica si el objeto existe antes de usarlo con FindFirstChild
Expected 'end'Olvidaste cerrar una function, bloque if o loopCuenta tus aperturas de function/if/for y asegúrate de que cada una tenga un end
Expected identifierError de escritura en una keyword o nombre de variableRevisa la ortografía cuidadosamente, Luau distingue entre mayúsculas y minúsculas
Infinite yield possibleWaitForChild está esperando algo que puede que nunca aparezcaAsegú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.