La respuesta corta
Para programar en Roblox Studio, pasa el ratón sobre ServerScriptService en el Explorer, haz clic en + e inserta un Script. Studio lo abre en el Script Editor. Escribe Luau, como print("Hello"), pulsa Play (F5) y lee el resultado en la ventana Output (menú Window o pestaña Script). Un Script se ejecuta en el servidor y cambia las cosas para todos; un LocalScript en StarterPlayerScripts se ejecuta en el dispositivo de un solo jugador.
- Aprende primero cuatro ideas: variables (
local coins = 3), funciones (local function name() ... end), sentencias if y eventos (part.Touched:Connect(...)). Los cuatro scripts de esta guía se construyen con eso, más bucles y tablas. - Usa
task.wait(), nowait(). La referencia de Roblox marca elwait()global como obsoleto y sustituido portask.wait(). - En las opciones de visualización de la ventana Output, activa Show Context para que cada línea diga si vino del Server o de un Client.
En esta página
Antes de empezar: Studio, un Baseplate y la ventana Output
Necesitas Roblox Studio y una cuenta de Roblox, y nada más: ni editor de código ni plugin. Todos los scripts de esta guía se escriben en el propio Script Editor de Studio.
- Instala Roblox Studio, la app gratuita de Roblox para Windows y Mac, e inicia sesión con tu cuenta de Roblox.
- Abre Studio. Su página de inicio muestra plantillas: elige Baseplate. Obtienes un suelo con una textura de cuadrícula de 4x4 y un SpawnLocation, el punto donde aparece tu avatar cuando juegas.
- Si no se ven las ventanas Explorer y Properties, ábrelas desde el menú Window o la pestaña Home. El Explorer muestra cada objeto de tu juego; Properties muestra los ajustes de lo que selecciones.
- Abre Output desde el menú Window o la pestaña Script. Ahí aparecen los mensajes y los errores de tus scripts.
- En las opciones de visualización de la ventana Output, activa Show Context, que etiqueta cada mensaje como Client o Server, y Show Source, que muestra el script y el número de línea que lo produjo.
| Script | Tipo | Dónde va | Qué enseña |
|---|---|---|---|
FirstScript | Script | ServerScriptService | Variables, una función, una sentencia if, bucles y una tabla |
ColourChanger | Script | Dentro de una Part en Workspace | Cambiar propiedades, script.Parent y un bucle que espera |
TouchPad | Script | Dentro de una Part llamada Pad | Eventos, encontrar al jugador que tocó una parte y un debounce |
MyFirstLocalScript | LocalScript | StarterPlayerScripts, dentro de StarterPlayer | Código que se ejecuta en el dispositivo de un jugador, pulsaciones de teclas y lo que se queda en ese dispositivo |
Workspace
Baseplate Part
SpawnLocation SpawnLocation
Part Part new
ColourChanger Script new
Pad Part new
TouchPad Script new
ServerScriptService
FirstScript Script new
StarterPlayer
StarterPlayerScripts
MyFirstLocalScript LocalScript new
Paso 1: escribe tu primer script
- En el Explorer, pasa el ratón sobre ServerScriptService, haz clic en el botón + y elige Script (el atajo es Ctrl+I, o ⌘I en Mac). Studio crea el script y lo abre en el Script Editor.
- Haz clic derecho en el script nuevo, elige Rename y llámalo
FirstScript. El nombre no cambia lo que hace el script, pero te dice qué script imprimió qué. - Los scripts nuevos empiezan con una línea,
print("Hello world!"). Bórrala y pega el código de abajo. - Pulsa Play (F5), con Test elegido en el desplegable de su izquierda. Studio inicia una prueba y pone tu avatar en el SpawnLocation.
- Lee las líneas del Output y pulsa Stop (Shift+F5). Stop también devuelve cada objeto a como estaba antes de pulsar Play, así que todo lo que moviste o recoloreaste mientras jugabas vuelve atrás.
-- Script en ServerScriptService llamado FirstScript.
-- Tu primer Luau: variables, una función, una sentencia if, un bucle y una tabla.
-- Pulsa Play (F5) y lee los resultados en la ventana Output.
-- Una variable es un nombre que guarda un valor
local gameName = "Coin Run"
local coinsToWin = 3
-- Una función es un bloque de código con nombre que puedes ejecutar las veces que quieras.
-- name y goal son sus parámetros; return devuelve un valor a quien la llamó.
local function describe(name: string, goal: number): string
return `{name}: collect {goal} coins to win`
end
print(describe(gameName, coinsToWin)) --> Coin Run: collect 3 coins to win
-- Una sentencia if ejecuta código solo cuando su condición es verdadera
if coinsToWin > 5 then
print("That is a long game")
elseif coinsToWin > 1 then
print("That is a short game")
else
print("One coin and you win")
end
-- Un bucle for repite código un número fijo de veces
for count = 1, coinsToWin do
print("Coin number", count)
end
-- Una tabla guarda una lista de valores; este bucle visita cada uno en orden
local colours = { "Red", "Green", "Blue" }
for position, colour in colours do
print(position, colour) --> 1 Red, luego 2 Green, luego 3 Blue
end
Todo lo que va después de -- en una línea es un comentario: Luau lo salta, así que puedes dejarte notas. Los comentarios --> muestran lo que imprime esa línea.
El Output debería mostrar estas ocho líneas, mezcladas con los mensajes del propio Studio. Cuando print recibe más de un valor, pone un espacio entre ellos. Con Show Context y Show Source activados, cada línea lleva además la etiqueta Server y FirstScript con un número de línea.
Coin Run: collect 3 coins to win
That is a short game
Coin number 1
Coin number 2
Coin number 3
1 Red
2 Green
3 Blue
Relaciona cada línea con el código que la imprimió. Más adelante harás lo mismo con los mensajes de error, así que vale la pena acostumbrarte desde ahora.
FirstScript usa solo Luau puro, sin objetos de Roblox, así que también funciona en el Luau playground gratis en tu navegador. Cambia un valor ahí y vuelve a ejecutarlo para ver qué cambia.
| Código | Idea | Qué significa |
|---|---|---|
local gameName = "Coin Run" | Variable | Un nombre que guarda un valor. local significa que solo este script, o el bloque en el que está, puede usarla. El texto entre comillas es un string (cadena); 3 es un number (número). Los nombres distinguen mayúsculas, así que coinsToWin y CoinsToWin son dos variables distintas. |
local function describe(name: string, goal: number): string | Función | Un bloque de código con nombre que puedes ejecutar las veces que quieras. name y goal son sus parámetros: valores que se le pasan cada vez que se llama. : string y : number son anotaciones de tipo opcionales. Luau las usa para avisarte de errores en el Script Editor; el código funciona igual sin ellas. |
return | Valor de retorno | Devuelve un valor al código que llamó a la función. print(describe(gameName, coinsToWin)) imprime lo que devuelva describe. |
`{name}: collect {goal} coins to win` | Interpolación de strings | El texto entre comillas invertidas puede contener valores: Luau sustituye {name} y {goal} por sus valores actuales. |
if, elseif, else, end | Sentencia if | Luau prueba las condiciones de arriba abajo y ejecuta solo la primera que sea verdadera. coinsToWin vale 3, que no es más que 5 pero sí más que 1, así que solo se imprime "That is a short game". |
for count = 1, coinsToWin do | Bucle for numérico | Ejecuta el código de dentro una vez por cada número de 1 a coinsToWin, con count valiendo 1, luego 2, luego 3. |
{ "Red", "Green", "Blue" } y for position, colour in colours do | Tabla y bucle | Una tabla usada como lista, lo que Luau llama un array. Las posiciones empiezan en 1, no en 0. El bucle visita cada elemento y te da su posición y su valor. |
Todo bloque que empieza con function, if, for o while se cierra con end. Un solo end que falte impide que se ejecute el script entero; leer los errores muestra el mensaje que recibes.
Paso 2: cambia una parte desde un script
Los scripts se vuelven útiles cuando cambian cosas en el mundo. Los ajustes que ves en la ventana Properties, como Color, Transparency o Anchored de una parte, son propiedades, y un script también puede cambiarlas.
- En la pestaña Home, haz clic en Part. Studio añade un bloque al Workspace. Su nombre da igual.
- En el Explorer, pasa el ratón sobre la parte nueva, haz clic en + e inserta un Script. Llámalo
ColourChangery sustituye su contenido por el código de abajo. - Pulsa Play. La parte se vuelve roja, luego azul, luego verde, cambiando una vez por segundo, y vuelve a empezar.
-- Script dentro de una Part en Workspace, llamado ColourChanger.
-- Los scripts cambian las mismas propiedades que ves en la ventana Properties.
-- Este da a su parte un color nuevo cada segundo, para todos los jugadores.
local part = script.Parent :: BasePart -- la parte dentro de la que está este script
local colours = {
Color3.fromRGB(255, 85, 85), -- rojo
Color3.fromRGB(85, 170, 255), -- azul
Color3.fromRGB(85, 255, 127), -- verde
}
part.Anchored = true -- una parte anclada se queda donde la pones
local index = 1
while true do
part.Color = colours[index]
index = index % #colours + 1 -- 1, 2, 3 y otra vez 1
task.wait(1) -- pausa de un segundo (el antiguo wait() está obsoleto)
end
script.Parentes el objeto dentro del que está el script, aquí la parte. Arrastra el script a otra parte y cambiará esa en su lugar.:: BasePartes una conversión de tipo (type cast). Le dice al Script Editor que el padre es una parte, para que pueda comprobar las propiedades que usas en él. Luau usa los tipos solo para avisos y sugerencias, así que la conversión no cambia lo que hace la línea.part.Colorypart.Anchoredson las mismas propiedades que ves en la ventana Properties, con los mismos nombres. Roblox usa la ortografía estadounidense, así que la propiedad esColoraunque este script se llame ColourChanger.Anchored = truemantiene la parte quieta: la referencia de Roblox dice que una parte anclada nunca se mueve por la gravedad, las colisiones ni ninguna otra física.colours[index]lee un elemento de la lista.#colourses la longitud de la lista, 3, y%da el resto de la división, así queindex % #colours + 1cuenta 1, 2, 3, 1, 2, 3.while true dose repite para siempre, por eso importa eltask.wait(1)de dentro. La documentación de Roblox dice que pongas siempre una pausa comotask.wait()en un bucle infinito: sin ella, el juego se congela y Studio se cuelga.
ColourChanger es un Script, así que se ejecuta en el servidor, y todos los jugadores del juego ven el mismo color a la vez. El paso 4 muestra el otro tipo de script.
Paso 3: reacciona a un jugador con un evento
La mayor parte del código de un juego espera a que pase algo: un jugador entra, se toca una parte, se hace clic en un botón. Roblox los llama eventos. Para ejecutar código cuando uno se dispara, le conectas una función.
- Inserta otra Part y llámala exactamente
Pad, con P mayúscula. Déjala directamente en el Workspace, no dentro de una carpeta o un modelo, porque el LocalScript del paso 4 la busca ahí. - Conviértela en una plataforma plana que puedas pisar, por ejemplo poniendo su
Sizea6, 1, 6en la ventana Properties. Muévela al suelo cerca del SpawnLocation y marca Anchored para que no se mueva. - Pasa el ratón sobre Pad, haz clic en +, inserta un Script, llámalo
TouchPady pega el código de abajo. - Pulsa Play y pisa la plataforma. Se vuelve amarilla durante 2 segundos, y el Output dice tu nombre.
-- Script dentro de una Part en Workspace llamada Pad, script llamado TouchPad.
-- Eventos: cuando un jugador pisa la plataforma, brilla en amarillo y el Output dice quién fue.
-- Un debounce evita que se ejecute muchas veces por segundo mientras está encima.
local Players = game:GetService("Players")
local pad = script.Parent :: BasePart
local COOLDOWN_SECONDS = 2
local normalColour = pad.Color
local busy = false
local function onTouched(otherPart: BasePart)
if busy then
return -- todavía en espera desde el último toque
end
-- El personaje es el Model que contiene la parte del cuerpo (o el sombrero) que tocó
local character = otherPart:FindFirstAncestorOfClass("Model")
local player = character and Players:GetPlayerFromCharacter(character)
if not player then
return -- la tocó una parte suelta o un NPC, no un jugador
end
busy = true
print(`{player.Name} stepped on the pad`)
pad.Color = Color3.fromRGB(255, 220, 0)
task.wait(COOLDOWN_SECONDS)
pad.Color = normalColour
busy = false
end
pad.Touched:Connect(onTouched)
| Código | Qué hace |
|---|---|
pad.Touched:Connect(onTouched) | Conecta la función al evento Touched de la plataforma, así que Roblox ejecuta onTouched cada vez que algo la toca, y le pasa la parte que la tocó. |
otherPart | La parte que tocó la plataforma: un pie, una pierna, el asa de un sombrero o una herramienta que lleva el jugador. Nunca es el jugador, así que las dos líneas siguientes averiguan de quién es. |
otherPart:FindFirstAncestorOfClass("Model") | Sube desde esa parte hasta el primer ancestro cuya clase sea exactamente Model, que es el personaje. Como el nombre de la clase debe coincidir exactamente, se salta un sombrero (clase Accessory) y una herramienta en la mano (clase Tool). |
Players:GetPlayerFromCharacter(character) | Devuelve el Player al que pertenece ese modelo como personaje, o nil si no es el personaje de nadie, como un NPC. El character and de delante se salta la llamada cuando no se encontró ningún modelo, lo que deja player en nil. |
if not player then return end | Se para aquí para todo lo que no sea un jugador. return sale antes de la función. |
Por qué la plataforma necesita un debounce
La página de debounce de Roblox advierte que Touched se dispara varias veces muy seguidas cuando las partes entran en contacto, y un personaje que camina tiene varias partes del cuerpo. Sin una comprobación, un solo paso sobre la plataforma podría imprimir muchas líneas y reiniciar el brillo amarillo una y otra vez.
La variable busy es el debounce. El primer toque la pone en true, y cada toque durante los 2 segundos siguientes llega a if busy then return end y se para. Después de task.wait(COOLDOWN_SECONDS) la plataforma vuelve a su color y busy vuelve a false. COOLDOWN_SECONDS va en mayúsculas porque es un ajuste que no cambia mientras el juego se ejecuta, la convención que sugiere Roblox para las constantes.
Esta plataforma tiene un solo debounce para todos, así que un segundo jugador que la pise en esos 2 segundos se ignora. Para una plataforma que brilla, está bien. Una plataforma que da recompensas debería llevar una espera por jugador, como hace la plataforma de monedas de la guía de leaderboard (en inglés).
Paso 4: tu primer LocalScript, y por qué es distinto
Un juego en marcha es un servidor más un cliente por cada jugador. Todo lo anterior era un Script, que se ejecuta en el servidor, así que sus cambios llegan a todos los jugadores. Un LocalScript, en cambio, se ejecuta en el dispositivo de un solo jugador. Las pulsaciones de teclas, la cámara y los menús en pantalla se gestionan ahí, porque solo ese dispositivo los conoce.
- En el Explorer, despliega StarterPlayer, pasa el ratón sobre StarterPlayerScripts, haz clic en + e inserta un LocalScript. Llámalo
MyFirstLocalScripty pega el código de abajo. - Pulsa Play. El Output muestra
Hello,y tu nombre, con la etiqueta Client. - Haz clic en la vista del juego y pulsa E. La plataforma se desvanece. Pulsa E otra vez para recuperarla.
- Con la prueba todavía en marcha, haz clic en el interruptor Client/Server de los controles de prueba de Studio para pasar a la copia del juego del servidor. Ahí la plataforma está sólida: el servidor nunca se enteró del cambio.
-- LocalScript en StarterPlayer > StarterPlayerScripts llamado MyFirstLocalScript.
-- Un LocalScript se ejecuta en el dispositivo de un jugador. Pulsa E: la Pad se desvanece solo en tu
-- pantalla, porque un cambio a una parte hecho aquí no llega al servidor ni a nadie más.
local Players = game:GetService("Players")
local UserInputService = game:GetService("UserInputService")
local player = Players.LocalPlayer
print(`Hello, {player.Name}`) -- aparece en el Output, marcado como Client
UserInputService.InputBegan:Connect(function(input: InputObject, gameProcessed: boolean)
if gameProcessed then
return -- la tecla se usó para otra cosa, como escribir en el chat
end
if input.KeyCode == Enum.KeyCode.E then
local pad = workspace:FindFirstChild("Pad")
if pad and pad:IsA("BasePart") then
pad.Transparency = if pad.Transparency == 0 then 0.6 else 0
end
end
end)
Players.LocalPlayeres el jugador cuyo dispositivo ejecuta el script. Roblox lo define solo para LocalScripts y los ModuleScripts que estos requieren, así que el código del servidor no puede usarlo.UserInputService.InputBeganse dispara cuando el jugador empieza una pulsación de tecla, un clic o un toque.gameProcessedestruecuando el motor ya usó esa entrada, por ejemplo un clic en un botón o una tecla escrita en la barra de chat, así que el script la ignora.workspace:FindFirstChild("Pad")devuelve el hijo llamado Pad, onilsi no hay ninguno.pad:IsA("BasePart")comprueba que de verdad es una parte antes de que el script cambie suTransparency.if pad.Transparency == 0 then 0.6 else 0es una expresión if: elige uno de dos valores. Una Transparency de 0 es totalmente visible y 1 es invisible.- Un script de sprint con Shift (en inglés) es un buen segundo LocalScript: escucha una tecla y cambia la WalkSpeed de tu personaje.
| Tipo | Se ejecuta en | Sus cambios llegan a | Úsalo para | Suele ir en |
|---|---|---|---|---|
| Script | El servidor | Todos los jugadores | Reglas del juego: monedas, daño, puertas, rondas, guardado | ServerScriptService, o dentro de una parte mientras aprendes |
| LocalScript | El dispositivo de un jugador | Solo ese dispositivo, salvo el movimiento de su propio personaje | Entradas, la cámara, menús en pantalla, efectos para un jugador | StarterPlayerScripts o StarterGui |
| ModuleScript | El lado que lo llama con require() | Lo mismo que el script que lo requirió | Código que comparten varios scripts | ReplicatedStorage para los dos lados, ServerScriptService solo para el servidor |
Lo que puede cambiar un tramposo
Da por hecho que un tramposo controla todo en su propio dispositivo. Puede ejecutar sus propios LocalScripts y cambiar los tuyos, así que puede desvanecer la plataforma, o cualquier otra cosa, en su propia pantalla. Aquí eso es inofensivo: el desvanecido es solo visual y se queda en su dispositivo. También es la razón por la que todo lo que importa lo decide un Script en el servidor.
Un Script de servidor tampoco es seguro automáticamente. TouchPad se ejecuta en el servidor, pero el dispositivo de cada jugador controla la física de su propio personaje, y la documentación de seguridad de Roblox incluye manipular cuándo se dispara Touched, o impedir que se dispare, entre lo que un cliente puede hacer con las partes que controla. Para una plataforma que brilla, da igual. Para una que paga, comprueba también algo que el servidor controle por sí mismo, como la regla de la guía de obby (en inglés) de que los checkpoints solo cuentan en orden.
Paso 5: prueba los cuatro scripts juntos
- Limpia el Output con Ctrl+K (⌘K en Mac) y pulsa Play (F5). El Output muestra las ocho líneas de FirstScript con la etiqueta Server, y tu línea Hello con la etiqueta Client. La parte de ColourChanger cambia de color cada segundo.
- Pisa la plataforma. Se vuelve amarilla durante 2 segundos y el Output muestra tu nombre y "stepped on the pad" una vez. Sigue caminando por encima: aparece una línea nueva como mucho una vez cada 2 segundos, no cada vez que se dispara Touched.
- Pulsa E. La plataforma se desvanece hasta una Transparency de 0.6. Pulsa E otra vez y está sólida.
- Pulsa Stop. En el desplegable de pruebas elige Server & Clients, pon 2 clientes y pulsa Play (o F7). Studio abre una ventana de servidor y dos de cliente. En un cliente, pulsa E: la plataforma se desvanece ahí, mientras el otro cliente y el servidor siguen viéndola sólida. Pulsa End Session al terminar.
- Rompe algo a propósito. Cambia el nombre de Pad a
Pad2y juega. Pisarla sigue volviéndola amarilla, porque TouchPad encuentra su parte conscript.Parent, no por el nombre. Pulsar E ahora no hace nada, y no hay error:FindFirstChild("Pad")devolviónil, y la comprobaciónif pad and ...se saltó el resto sin decir nada. Añadeprint(pad)en la línea después deFindFirstChild, juega y pulsa E: el Output muestranil. Un print así es la forma más rápida de averiguar por qué un script no hace nada. Pulsa Stop, borra la línea del print y vuelve a llamar Pad a la parte.
Dónde van los scripts
Dónde está un script decide si llega a ejecutarse, y Studio no te avisa cuando nunca lo hará. Para los scripts que escribirás a continuación:
| Contenedor | Pon aquí | Por qué |
|---|---|---|
| ServerScriptService | Scripts con la mayoría de las reglas de tu juego: recompensas, rondas, guardado | Se ejecutan en el servidor, y nada de ServerScriptService se envía a los jugadores. |
| Dentro de una parte en Workspace | Un Script que pertenece a esa parte, como ColourChanger y TouchPad | Vale mientras aprendes: la parte es script.Parent. Para proyectos reales, Roblox aconseja etiquetar las partes (ver abajo). |
| StarterPlayerScripts, dentro de StarterPlayer | La mayoría de los LocalScripts: entradas, la cámara, efectos para un jugador | Cada jugador recibe su propia copia al entrar. |
| StarterGui | LocalScripts dentro de una ScreenGui que manejan un menú en pantalla | Cada jugador recibe su propia copia de la interfaz. |
| ReplicatedStorage | ModuleScripts que requieren tanto el código del servidor como el del cliente | Los dos lados pueden verlo. Un LocalScript, o un Script con los ajustes por defecto, puesto aquí nunca se ejecuta. |
La página de ubicaciones de scripts de Roblox recomienda no poner scripts directamente dentro de partes en Workspace: etiqueta las partes y trabaja con ellas desde un único ModuleScript usando CollectionService. Un script dentro de una parte sigue siendo la forma más fácil de empezar, y vale para uno o dos objetos mientras aprendes. La guía de puertas muestra el patrón con etiquetas, con un solo script para todas las puertas, y la guía de cliente y servidor (las dos en inglés) tiene la tabla completa de qué contenedores ejecutan qué scripts.
Cuando algo sale mal: lee el Output
Los errores aparecen en rojo en el Output. Cada uno empieza con dónde pasó, el nombre completo del script y el número de línea, y luego dice qué salió mal. Haz clic en el error y Studio abre ese script en esa línea. Por ejemplo, si borraras la comprobación if not player de TouchPad y cayera una parte suelta sobre la plataforma, el Output mostraría:
Workspace.Pad.TouchPad:22: attempt to index nil with 'Name'
Los errores en cómo está escrito el código, como un end que falta, aparecen antes de pulsar Play: el Script Editor los subraya en rojo, y la ventana Script Analysis (el botón Analysis de la pestaña Script) los enumera. Un script con uno de estos errores no se ejecuta en absoluto, ni siquiera las líneas de antes.
| Mensaje | Qué significa | Solución |
|---|---|---|
Colour is not a valid member of Part "Workspace.Part" | No existe nada con ese nombre exacto en ese objeto. Aquí, la propiedad se escribe Color. | Copia la ortografía y las mayúsculas de la ventana Properties o del Explorer. Más sobre este error. |
attempt to index nil with 'Name' | El código leyó algo, aquí .Name, de un valor que era nil. En el ejemplo de arriba, player era nil porque una parte suelta tocó la plataforma. | Averigua por qué el valor es nil, y compruébalo con if antes de usarlo. Más sobre este error. |
Expected 'end' (to close 'then' at line 2), got <eof> | El if de la línea 2 no tiene su end. Para una función el mensaje dice to close 'function', y <eof> significa el final del archivo. | Añade el end que falta, mirando la línea que indica el paréntesis y no la última. A veces el mensaje termina con "did you forget to close ... at line N?". Esa parte es una suposición de Luau a partir de tu sangría y puede señalar el bloque equivocado, así que revisa primero la línea del paréntesis. Más sobre errores de sintaxis. |
Cuando un script no hace nada y el Output tampoco muestra nada, suele estar en un sitio donde nunca se ejecuta, o esperando un evento que nunca se dispara. La guía de errores de scripts (en inglés) tiene una lista para scripts silenciosos y profundiza en cómo leer el Output.
Qué hacen distinto los tutoriales de scripting antiguos
Si también aprendes con videos y publicaciones de foros, te encontrarás patrones antiguos. Estos son los que importan, con el motivo por el que cada uno es un problema.
| El tutorial | El problema | Esta guía |
|---|---|---|
Hace pausas con wait(1) | La referencia de Roblox marca el wait() global como obsoleto y dice que task.wait() lo ha sustituido. | task.wait(1) |
Encuentra el personaje con otherPart.Parent, como hace la propia lección de lava de Roblox | Cuando un sombrero o una herramienta en la mano toca la parte, otherPart.Parent es el Accessory o la Tool, no el personaje, así que no se encuentra ningún Humanoid y ese toque se pierde. | FindFirstAncestorOfClass("Model"), y luego GetPlayerFromCharacter |
Usa Touched sin debounce | Touched se dispara varias veces muy seguidas por un solo paso, así que el código se ejecuta una y otra vez. | Una variable busy y una espera |
| Pone un LocalScript dentro de una parte en Workspace | Ahí un LocalScript nunca se ejecuta. Solo funciona desde lugares que pertenecen a un jugador. | LocalScripts en StarterPlayerScripts (por qué) |
Escribe part.Touched:connect(...) o table.getn(list) | La guía de nombres de Roblox dice que las APIs en camelCase están en su mayoría obsoletas, y la referencia solo incluye Connect. table.getn está obsoleto en favor de #list. | :Connect(...) y #list |
| Cambia monedas o hace daño en un LocalScript | El cambio se queda en el dispositivo de ese jugador, así que nadie más lo ve y el servidor nunca lo cuenta. | Reglas del juego en Scripts en el servidor |
Práctica: tres cambios para probar
Cambiar código enseña más que leerlo. Prueba estos en tu propio juego, de uno en uno, y pulsa Play después de cada uno.
- Haz que la plataforma dé un punto. Añade el script Leaderstats del paso 1 de la guía de leaderboard (en inglés). Luego en TouchPad, después de
busy = true, busca la carpetaleaderstatsdel jugador y suma 1 a su valorCoins. Pista:player:FindFirstChild("leaderstats"), luegoleaderstats:FindFirstChild("Coins"), luegocoins.Value += 1. La plataforma de monedas de la guía de leaderboard es una versión terminada, con una espera por jugador. - Desvanece también el cambiador de color. Haz que ColourChanger cambie también la
Transparencyde la parte cada segundo. Pista: añade una segunda tabla de números entre 0 y 1, como{ 0, 0.3, 0.6 }, y ponpart.Transparencya partir de ella en la línea después depart.Color, usando el mismoindex. - Imprime el color de la plataforma. Haz que MyFirstLocalScript imprima el
Colorde la plataforma cuando pulses E. Pista:print(pad.Color)dentro del bloqueif pad and pad:IsA("BasePart"). Pulsa E mientras la plataforma está amarilla: el cliente ve el color que puso el servidor, porque los cambios hechos en el servidor llegan a todos los clientes.
Qué aprender después
Ya has usado las piezas con las que se construyen la mayoría de los scripts de juegos. Un buen orden para lo que viene:
- LocalScript vs Script vs ModuleScript: dónde se ejecuta cada tipo de script y qué puede cambiar, con más detalle que el paso 4.
- RemoteEvents: cómo un LocalScript le pide al servidor que haga algo, y cómo el servidor comprueba la petición.
- Una tabla de clasificación: tus primeras estadísticas, creadas y cambiadas en el servidor.
- Tu primer juego: un recorrido corto con lava, monedas y una meta, dirigido por dos scripts de servidor, y luego publicado.
- Luego elige un sistema que añadir: una tienda con GUI, un sistema de rondas, checkpoints de obby, una pantalla de carga o una animación al pulsar una tecla. Cuando algo se rompa, la guía de errores de scripts te ayuda a leer el mensaje. Estas guías están en inglés.
Los tutoriales Coding fundamentals de Roblox (en inglés) son un buen complemento: seis series que van de variables y funciones a condicionales, bucles, arrays y diccionarios, hasta organizar el código con ModuleScripts, con pequeños proyectos para construir en Studio.
Errores comunes y soluciones
La mayoría de los problemas con un primer script son un nombre que no coincide, un script en el lugar equivocado o un bucle sin espera. Deja el Output abierto mientras pruebas.
Studio se congela o deja de responder al pulsar Play
Un bucle while true do no tiene ninguna espera dentro, así que nada más llega a ejecutarse. La documentación de Roblox dice que un bucle infinito sin una pausa como task.wait() congela el juego y cuelga Studio. Pon un task.wait() dentro de cada bucle que se repita para siempre, como hace ColourChanger.
No pasa nada cuando piso la plataforma
Comprueba que TouchPad es un Script, no un LocalScript, directamente dentro de la parte Pad, que no está desactivado y que la propiedad CanTouch de la plataforma está marcada. Luego pon print("touched", otherPart.Name) como primera línea dentro de onTouched. Si nunca se imprime, el evento no se dispara; si se imprime, el problema está más abajo.
Pulsar E no hace nada
MyFirstLocalScript tiene que ser un LocalScript dentro de StarterPlayerScripts: un LocalScript en Workspace o en ServerScriptService nunca se ejecuta. La parte tiene que llamarse exactamente Pad y estar directamente en el Workspace. Haz clic primero en la vista del juego, y asegúrate de que no estás escribiendo en el chat, porque el script ignora las teclas que el juego ya usó.
La parte cambia en mi pantalla pero no para los demás jugadores
El cambio se hizo en un LocalScript, así que se quedó en tu dispositivo. Hazlo en un Script de servidor, o que el LocalScript se lo pida al servidor con un RemoteEvent.
ColourChanger funciona dentro de una parte pero falla en ServerScriptService
Usa script.Parent como su parte. En ServerScriptService el padre es ServerScriptService, que no tiene Anchored ni Color, así que el Output muestra un error "not a valid member". Déjalo dentro de la parte, o dale un nombre a la parte y búscala por ese nombre, por ejemplo local part = workspace:WaitForChild("ColourPart") :: BasePart.
El Output no muestra nada
Comprueba que la ventana Output está abierta (menú Window o pestaña Script) y que no hay ningún filtro: el Output se puede filtrar por tipo de mensaje, por Client o Server y por texto. Si está abierta y sigue vacía, probablemente el script nunca se ejecutó. Consulta la lista para scripts que no hacen nada (en inglés).
Desatascarte con RoCode
Si te atascas con un script en tu propio juego, RoCode puede leerlo contigo. RoCode es un agente de IA independiente para Roblox Studio, no lo hace Roblox: escribes en un chat web y su plugin de Studio crea y edita los scripts de tu Explorer.
Mientras aprendes, el modo útil es Ask: los scripts los sigues escribiendo tú, y RoCode lee lo que ya hay y responde tus preguntas.
Explícame línea por línea qué hace el script TouchPad que está dentro de la parte Pad, y dime por qué usa un debounce.
- En modo Ask, usa solo herramientas de lectura como Search Scripts y Read Script, y no cambia nada en el juego
- Si algo necesita corrección, dice qué cambiaría y dónde, y sugiere pasar a Build
- En Build edita los scripts en el sitio y comprueba con Check Script que cada uno compila. Es una comprobación de compilación, no de tipos ni una prueba de juego
- Lee el Output de Studio con su herramienta Check Output, incluidas las líneas Server y Client de tu última prueba, incluso después de pulsar Stop
En modo Build con el plugin 3.9 o posterior, RoCode puede hacer una prueba corta y leer los errores, y con el plugin 3.9.11 o posterior controlar un personaje de prueba para comprobar que el juego funciona, pero no toma capturas mientras el juego se ejecuta, así que la plataforma la sigues pisando tú. Cómo se conecta RoCode a Studio.
Preguntas frecuentes
¿Dónde escribo scripts en Roblox Studio?
En el Explorer, pasa el ratón sobre un contenedor como ServerScriptService, haz clic en el botón + y elige Script. Studio lo abre en el Script Editor, donde escribes Luau. Los scripts de servidor suelen ir en ServerScriptService; los LocalScripts van en StarterPlayerScripts o StarterGui.
¿Cómo ejecuto un script en Roblox Studio?
Pulsa Play (F5). Studio inicia una prueba, y cada Script activado en ServerScriptService o Workspace se ejecuta en cuanto empieza el juego; los LocalScripts de StarterPlayerScripts se ejecutan cuando entras en la prueba. Run (elígelo en el desplegable junto a Play, o pulsa F8) inicia el juego sin tu avatar, así que para esta guía usa Play. Pulsa Stop (Shift+F5) para terminar la prueba. Para abrir un script que ya tienes, haz doble clic en él en el Explorer.
¿Qué lenguaje de programación usa Roblox?
Luau. Roblox lo describe como un lenguaje de scripting rápido, pequeño, seguro y con tipado gradual, derivado de Lua 5.1, así que la mayoría de los tutoriales de Lua siguen sirviendo. Luau añade funciones como la interpolación de strings con comillas invertidas y las anotaciones de tipo opcionales, y Roblox añade sus propias bibliotecas y objetos, como task.wait.
¿Qué diferencia hay entre un Script y un LocalScript?
Un Script se ejecuta en el servidor, y sus cambios llegan a todos los jugadores. Un LocalScript se ejecuta en el dispositivo de un jugador, para cosas como las entradas, la cámara y los menús en pantalla, y sus cambios en partes, valores y la interfaz se quedan en ese dispositivo. La guía de cliente y servidor (en inglés) cubre los dos, más los ModuleScripts.
¿Puedo programar en Roblox Studio en un teléfono o un iPad?
La página de configuración de Roblox describe Studio como una app gratuita para Windows y Mac y no indica ninguna versión para teléfono o tableta, así que necesitas una computadora para escribir scripts.
¿Por qué mi script no hace nada y no muestra ningún error?
Normalmente está en un sitio donde ese tipo de script no se ejecuta (un LocalScript en Workspace, o un Script en StarterPlayerScripts), está desactivado, o el evento que espera nunca se dispara. La guía de errores de scripts tiene una lista de comprobación (en inglés).
¿Cuánto se tarda en aprender a programar en Roblox?
Nadie puede darte un número honesto: depende de cuánto construyas. Lo que más ayuda es escribir scripts pequeños en tu propio juego a menudo. Cambia los cuatro scripts de aquí, prueba las tareas de práctica, luego sigue la guía de tu primer juego y añade un sistema a la vez.
Fuentes y lecturas
- Roblox Creator Docs: Luau (en inglés). qué es Luau y de dónde viene
- Roblox Creator Docs: Roblox Studio setup (en inglés). Windows y Mac, y los requisitos del sistema
- Roblox Creator Docs: Output (en inglés). abrir el Output, filtros, Show Context y Show Source
- Roblox Creator Docs: Studio testing modes (en inglés). Play, Run, Stop, el interruptor Client/Server y Server & Clients
- Roblox Creator Docs: Script Editor (en inglés). dónde se abren los scripts nuevos, y Script Analysis
- Roblox Creator Docs: Script types and locations (en inglés). dónde se ejecuta cada tipo de script, y etiquetar partes en lugar de poner scripts dentro
- Roblox Creator Docs: Script (en inglés). cuándo empieza a ejecutarse un Script
- Roblox Creator Docs: Control structures (en inglés). sentencias if, bucles, y por qué un bucle infinito necesita una espera
- Roblox Creator Docs: Events (en inglés). Connect, y lo que Touched pasa a tu función
- Roblox Creator Docs: Debounce patterns (en inglés). por qué Touched se dispara varias veces por un solo contacto
- Roblox Creator Docs: wait (en inglés). el wait() global y task.wait()
- Roblox Creator Docs: Network ownership, movement validation and physics exploits (en inglés). lo que un cliente puede hacer con su propio personaje
- Roblox Creator Docs: Coding fundamentals (en inglés). la serie para principiantes de Roblox
Cómo se comprobó el código: cada script de esta página pasa el verificador de tipos estricto de Luau con las definiciones de la API de Roblox (luau-lsp, 26 de octubre de 2026). Una verificación de tipos detecta APIs mal escritas y tipos incorrectos, no la lógica del juego, así que pruébalo en Studio antes de publicar.