Que tu juego no vaya a tirones: guía de optimización

Claim Your Loot

·

Portada del artículo «Que tu juego no vaya a tirones», de la sección Roblox Studio

Tu juego va perfecto en tu ordenador y a tus amigos les da bandazos. No es que tengan un cacharro: es que la mayoría de la gente juega en el móvil, y ahí lo que a ti te sobra a ellos les falta.

Lo bueno es que casi todos los tirones vienen de cuatro o cinco cosas concretas, y ninguna requiere ser un experto en gráficos.

En la demo tienes un presupuesto: mueve las partes, las luces, las transparencias y los scripts en bucle, y mira qué se lleva el dinero.

Respuesta rápida

Los cuatro sospechosos, por orden: partes de más, luces dinámicas, transparencias amontonadas y scripts que se ejecutan cada fotograma. Antes de tocar nada, abre el micro-perfilador (Ctrl + F6 en Studio) y mira quién se está comiendo el tiempo.

Lo que necesitas antes de empezar

  • Un lugar que ya vaya regular, para notar la diferencia.
  • Unos 40 minutos.

Paso 1: medir antes de tocar

Optimizar a ciegas es perder la tarde. Dos herramientas:

  • Micro-perfilador (Ctrl + F6): te enseña en qué se va cada fotograma. Si la barra grande es de scripts, el problema es tu código; si es de renderizado, el problema es lo que hay en pantalla.
  • F9 (consola de desarrollo), pestaña de memoria: cuánto ocupa cada cosa. Aquí es donde se descubren las texturas de 4K en un cubo de dos metros.

Apunta el número antes y después de cada cambio. Sin eso, no sabes si mejoraste o empeoraste.

Los cuatro sospechosos del rendimiento y la solución de cada uno

Paso 2: partes que no tienen por qué existir

Lo más habitual, con diferencia:

  • Lo que no se ve nunca. El interior de las paredes, la parte de abajo de las plataformas, los cimientos del edificio. Bórralo.
  • Las partes decorativas repetidas mil veces. Cien vallas idénticas se dibujan cien veces. Si son iguales, conviértelas en un solo modelo y usa MeshPart, o al menos agrúpalas.
  • Los modelos gratis del catálogo. Muchos traen dentro cincuenta partes para hacer lo que tú harías con tres. Ábrelos y mira antes de dejarlos.

Y tres propiedades que son gratis y ayudan:

parte.CanCollide = false   -- si no hace falta chocar
parte.CanTouch = false     -- si no hace falta detectar contacto
parte.CanQuery = false     -- si no hace falta que salga en rayos ni búsquedas
parte.CastShadow = false   -- en adornos pequeños, esto se nota mucho

CastShadow = false en la decoración pequeña (piedras, flores, vallas) es de las cosas que más rendimiento devuelven por menos trabajo.

Paso 3: las luces

Cada luz dinámica cuesta, y cuestan mucho más cuando se solapan. Reglas prácticas:

  • Un puñado de luces bien puestas se ve mejor que treinta repartidas.
  • Baja el Range. Una luz con rango 60 ilumina —y cuesta— en toda esa esfera.
  • Si una luz nunca cambia, plantéate si la necesitas o si te vale con un material Neon y una textura clara.
  • Shadows = false en las luces pequeñas de adorno.

Paso 4: transparencias

Es la que menos se conoce. Cuando miras a través de varias superficies transparentes seguidas (cristales, humo, agua, hierba con transparencia), la tarjeta tiene que dibujar todas, una detrás de otra. Cinco cristales alineados cuestan cinco veces.

  • Evita amontonar transparencias en la misma línea de visión.
  • La hierba y las hojas con textura transparente son carísimas en móvil. Menos y más grandes.
  • Las partículas también cuentan: Rate alto con partículas grandes es el clásico «al entrar en la cueva baja a la mitad».

Paso 5: los scripts

El error que hunde juegos enteros:

-- MAL: se ejecuta 60 veces por segundo, para siempre
game:GetService("RunService").Heartbeat:Connect(function()
	for _, jugador in ipairs(game.Players:GetPlayers()) do
		comprobarZonas(jugador)      -- recorre 200 zonas
	end
end)

Eso son 12.000 comprobaciones por segundo para algo que no cambia tan deprisa. Casi siempre se arregla con dos ideas:

-- BIEN: cada 0,3 s sobra, y no se nota
while true do
	task.wait(0.3)
	for _, jugador in ipairs(game.Players:GetPlayers()) do
		comprobarZonas(jugador)
	end
end

Y mejor todavía: que no haya bucle. Si algo pasa cuando el jugador entra en una zona, usa un evento en vez de preguntar sesenta veces por segundo si ya entró.

Otras dos que valen mucho:

  • Guarda lo que no cambia. workspace:FindFirstChild("Mapa") dentro de un bucle es trabajo repetido: sácalo fuera.
  • Desconecta lo que ya no usas. Cada Connect que no desconectas sigue vivo. Guarda la conexión y llama a :Disconnect() cuando el objeto muera.

Paso 6: StreamingEnabled

En Workspace, la propiedad StreamingEnabled hace que a cada jugador solo se le mande la parte del mapa que tiene cerca. En mapas grandes es la diferencia entre entrar en veinte segundos o en tres.

Lo que hay que saber antes de activarlo:

  • Los scripts del cliente ya no pueden dar por hecho que el mapa entero existe. Hay que usar WaitForChild y comprobar que las cosas están.
  • Las partes importantes que siempre deben existir se marcan con ModelStreamingMode en persistente.
  • Prueba el juego entero después de activarlo: es un cambio que rompe cosas si tu código era descuidado.

Paso 7: la lista de la compra en móvil

Si solo vas a hacer cinco cosas, que sean estas:

  1. Borrar lo que no se ve.
  2. CastShadow = false en toda la decoración pequeña.
  3. Reducir luces dinámicas y su rango.
  4. Cambiar los bucles de cada fotograma por bucles cada 0,2-0,5 s.
  5. Activar StreamingEnabled si el mapa es grande.

Reparte el presupuesto

Quién se está comiendo tu fotograma

Mueve las cuatro palancas y mira dónde se va el coste. No son fotogramas por segundo reales: es el peso relativo de cada cosa, que es justo lo que hay que aprender a mirar.

Reparto del coste

Presupuesto gastado
Lo primero, medir: Ctrl + F6 abre el micro-perfilador

Errores habituales

«He optimizado y no ha mejorado nada»

Optimizaste lo que no era. Mira el micro-perfilador: si el tiempo se va en renderizado, tocar scripts no cambia nada.

Unir todo el mapa en una sola Union

Las uniones grandes son caras de calcular y peores de colisionar que las partes sueltas. Une lo que tenga sentido geométrico, no por juntar.

Texturas enormes en objetos pequeños

Una textura de 1024 en un cubo que se ve del tamaño de una moneda es memoria tirada. Mira la pestaña de memoria en F9.

El juego va bien vacío y fatal con veinte jugadores

Entonces es el servidor, no el gráfico: busca scripts que hagan trabajo por jugador. Multiplica siempre por el número de jugadores que esperas.

Cientos de partes creadas y nunca borradas

Los efectos, los drops y las balas hay que borrarlos: game:GetService("Debris"):AddItem(parte, 5). Sin eso, el juego se va llenando hasta que se atasca.

Todo va bien en Studio y mal en el juego publicado

En Studio, el servidor y el cliente son tu mismo ordenador y no hay red por medio. Prueba siempre publicado y con gente.

Preguntas frecuentes

¿Cuántas partes puedo tener?

No hay un número. Importa más cuántas se ven a la vez, cuántas se mueven y cuántas tienen físicas activas que el total del mapa. Si el peso te lo está dando el terreno, mira cómo hacer un mapa sin pasarte de tamaño.

¿MeshPart o Union?

Para formas complicadas y repetidas, MeshPart (modelado fuera y traído). Union está bien para cosas puntuales.

¿Anclar las partes ayuda?

Muchísimo. Todo lo que no se tenga que mover, anclado: el motor de físicas se lo salta.

¿Y las animaciones y el sonido?

Los sonidos con rango grande y las animaciones de muchos personajes a la vez también cuestan. Si tienes cien NPC animados, ahí tienes tu problema. Con el sonido pasa parecido, y se explica en dónde va cada objeto Sound.

¿Cómo sé si va bien en móvil si no tengo móvil?

En Studio, el emulador de dispositivos te da el tamaño y los controles, pero no el rendimiento real. Para eso hay que probarlo en un móvil real, y a poder ser en uno viejo.


Última revisión: 1 de septiembre de 2026

Claim Your Loot

Explora otras secciones

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *