Técnicas y conversión

*Este contenido se traduce usando la IA (Beta) y puede contener errores. Para ver esta página en inglés, haz clic en aquí.

Esta guía describe varias técnicas para usar el streaming de instancias en el juego de manera eficiente y efectiva. Si bien no hay una solución "talla única" para diseñar un juego de streaming, seguir estos pasos de alto nivel te llevará la mayor parte del camino.

Propiedades de streaming

Una vez que StreamingEnabled está activado para el objeto Workspace en Studio, establece sus propiedades relacionadas a los siguientes valores recomendados:

PropiedadRecomendación
EnableSLIMAvatarsUsa Enabled para renderizar avatares de rig estándar como representaciones ligeras y animadas cuando sea apropiado. Consulta avatares SLIM para más información.
ModelStreamingBehaviorUsa Improved para habilitar el streaming más eficiente para Models con descendientes de BasePart.
StreamingIntegrityModeUsa PauseOutsideLoadedArea para equilibrar la integridad del juego sin pausar innecesariamente o con demasiada frecuencia.
StreamingMinRadiusUsa el valor predeterminado de 64 para maximizar cuánto puede reducir el motor el juego para dispositivos de gama baja.
StreamingTargetRadiusUsa el valor predeterminado de 1024 para lograr un buen equilibrio entre la visibilidad para los jugadores en dispositivos de gama alta y una huella de memoria razonable.
StreamOutBehaviorUsa Opportunistic para permitir que el cliente recolecte agresivamente contenido no utilizado, reduciendo significativamente el uso de memoria y ayudando a prevenir bloqueos por falta de memoria.

Nivel de detalle del modelo

Model.LevelOfDetail ayuda a llenar el contenido de Model no transmitido con mallas compuestas ligeras o impostores, haciendo que el mundo se vea visualmente completo. SLIM (Modelos Interactivos Ligeros Escalables) son particularmente efectivos, ya que los jugadores a menudo no pueden distinguir una malla SLIM del original completamente transmitido.

Para obtener los mejores resultados:

  • Agrupa partes que están espacial y lógicamente relacionadas, por ejemplo, todas las partes de un coche.
  • Establece LevelOfDetail a SLIM en modelos que contienen mallas y partes estáticas. Los modelos que se modifican en tiempo de ejecución o que reproducen animaciones no son compatibles.
  • Mantén la extensión espacial de cada modelo por debajo de ~64 studs cúbicos para aumentar la probabilidad de que el modelo completo se transmita junto. Si un modelo tiene extensiones muy grandes, divídelo en modelos modulares más pequeños y aplica un LevelOfDetail apropiado a cada uno.

Estructura del modelo

Más allá de establecer el nivel de detalle del modelo, la estructura y configuración de tus Models tiene un impacto significativo en el rendimiento del streaming. A medida que construyes o conviertes un juego existente:

  • Usa modelos atómicos para agrupación lógica — Cuando un script necesita acceso a todas las partes dentro de un modelo, establece su ModelStreamingMode a Atomic. Esto permite que los scripts del lado del cliente accedan de manera segura a las instancias dentro del modelo sin un uso excesivo de WaitForChild() (aunque tales scripts aún deben usar WaitForChild() para el modelo atómico en general).

  • Minimiza los modelos persistentes — Los modelos persistentes se cargan después de unirse y nunca se transmiten, ocupando memoria de forma permanente. Establece el ModelStreamingMode de un modelo a Persistent solo si debe permanecer disponible y accesible para los scripts en todo momento.

  • Descompón los modelos contenedores — Un patrón común no streaming es un único Model enorme que contiene muchos NPCs, props o agrupaciones similares. Bajo streaming, los modelos contenedores disminuyen la eficiencia del streaming y no son óptimos para el nivel de detalle del modelo que funciona mejor con instancias agrupadas de cerca. Descompón los modelos contenedores en modelos más pequeños con partes físicamente cercanas o lógicamente relacionadas.

  • Aplana jerarquías de modelos profundamente anidadas — Anidar un modelo persistente dentro de un modelo atómico efectivamente obliga al modelo atómico a comportarse como persistente. Las jerarquías planas son más fáciles de razonar bajo streaming.

Avatares SLIM

Los avatares de plataforma fuera del área actualmente transmitida no son visibles por defecto, pero habilitar Workspace.EnableSLIMAvatars renderiza avatares de rig estándar como representaciones ligeras y animadas cuando es apropiado. Efectivamente, el motor:

  • Renderiza una versión SLIM cuando un modelo de avatar real se transmite fuera.
  • Cambia entre representaciones SLIM y de alta resolución según los recursos disponibles, incluso dentro del radio de streaming.
  • Limita las animaciones SLIM según la importancia de la escena y el ancho de banda disponible.

Los avatares SLIM son compatibles con personajes de jugadores de rig estándar R15 con cuerpo, cabeza, ropa en capas y accesorios. Los avatares R6, NPCs y avatares con proporciones personalizadas están excluidos. Para la lista completa de configuraciones de avatares compatibles y excluidas, datos de rendimiento y consejos de solución de problemas, consulta avatares SLIM.

Patrones de script

Los siguientes patrones de script son los más comúnmente afectados por el streaming. La estrategia correcta depende de la intención del código, por lo que cada patrón enumera múltiples opciones donde sea apropiado.

Índice directo a descendientes

Indexar en los descendientes de Workspace con el operador . genera un error si alguna instancia en la ruta no está actualmente transmitida. Lo mismo se aplica a FindFirstChild(), FindFirstChildWhichIsA() y FindFirstChildOfClass() que devuelven nil si el hijo no se ha transmitido.

Búsqueda de Descendientes
local house1 = workspace:FindFirstChild("House1") -- nil si "House1" no se ha transmitido
local door = workspace.House1.Door -- Roto si "House1" o "Door" no se han transmitido

Un patrón similar es acceder a Humanoid u otros descendientes del personaje directamente dentro de una conexión Player.CharacterAdded. Bajo streaming, el modelo del personaje se parenta a Workspace antes de que todos sus descendientes se hayan replicado, por lo que el indexado directo falla.

Descendientes del Personaje
local Players = game:GetService("Players")
local player = Players.LocalPlayer
player.CharacterAdded:Connect(function(character)
local humanoid = character.Humanoid
end)

Si el script no puede avanzar sin una instancia, espera a que esté disponible con WaitForChild():

Búsqueda de Descendientes
local house1 = workspace:WaitForChild("House1")
local door = house1:WaitForChild("Door")

Instancias enviadas de forma remota

Una señal de RemoteEvent/RemoteFunction y la instancia a la que se refiere viajan independientemente, por lo que la señal puede llegar al cliente antes de que la instancia esté presente — o la instancia puede no estar presente en absoluto. Dos causas probables incluyen:

  • Bajo streaming, puede haber un ligero retraso entre cuando una parte/modelo se crea en el servidor y cuando se replica a los clientes. Efectivamente, una parte referenciada por un RemoteEvent/RemoteFunction puede simplemente no existir aún, incluso dentro de un área transmitida.

  • Enviar una referencia de parte/modelo del servidor al cliente a través de un RemoteEvent o RemoteFunction requiere que la instancia se replique al cliente receptor. Enviar una ruta de instancia como una cadena tiene el mismo problema, ya que la ruta puede resolverse a una ubicación no existente en el cliente:

    Script del Cliente
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local remoteEvent = ReplicatedStorage:FindFirstChildOfClass("RemoteEvent")
    remoteEvent.OnClientEvent:Connect(function(data)
    local checkpoint = data.checkpoint -- Errores si "checkpoint" no se ha transmitido
    local level = workspace.Levels[data.levelPath] -- Errores si la ruta no se ha transmitido
    end)

Si el script del cliente receptor necesita la instancia para continuar, incluye WaitForChild() antes de usarla. Ten en cuenta que esto puede esperar indefinidamente si la instancia nunca se transmite, así que considera agregar un tiempo de espera como segundo parámetro de WaitForChild().

Desincronización del cliente

La desincronización del lado del cliente debe tratarse como una excepción, no como un patrón de diseño estándar. Introducir copias solo del cliente o reparentar instancias localmente puede crear problemas graves. Audita tu código en busca de lugares que dependan de estos tipos de cambios que persisten en el cliente.

Por ejemplo, reparentar una instancia localmente de ReplicatedStorage a Workspace puede hacer que esa instancia sea elegible para ser transmitida. De manera similar, clonar una instancia localmente (Instance:Clone()) de ReplicatedStorage en Workspace crea una copia solo del cliente que ya no forma parte del pipeline de replicación del servidor y no recibirá actualizaciones de propiedades de la instancia original propiedad del servidor.

El mismo concepto se aplica al llamar a Instance:Destroy() en el cliente para un objeto propiedad del servidor. Esto elimina la instancia localmente, pero el servidor aún la tiene, por lo que se transmitirá nuevamente con su estado original cuando sea elegible.

Streaming proactivo

Cuando se puede anticipar el próximo destino de un jugador, realiza llamadas del lado del servidor a Player:RequestStreamAroundAsync() para transmitir áreas transitorias para una carga temporal, o usa Player:AddReplicationFocus() de manera limitada para áreas que deben permanecer cargadas hasta que se liberen explícitamente.

Por ejemplo, cuando un personaje jugador está a punto de teletransportarse mediante un cambio de CFrame a la casa de otro jugador en una ubicación distante, puedes pre-cargar el área de destino para minimizar el pop-in y proporcionar una transición más suave. El siguiente script muestra cómo se puede activar un evento remoto del cliente al servidor para mover un personaje jugador utilizando un método de pre-carga. Si la solicitud de pre-carga tiene éxito cuando la función retorna, el radio mínimo alrededor de la ubicación objetivo debería estar presente en el cliente.

Script del Servidor - Teletransportar Personaje Jugador
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local teleportEvent = ReplicatedStorage:WaitForChild("TeleportEvent")
local function teleportPlayer(player, teleportTarget)
-- Solicitar streaming alrededor de la ubicación objetivo
player:RequestStreamAroundAsync(teleportTarget)
-- Teletransportar personaje
local character = player.Character
if character and character.Parent then
local currentPivot = character:GetPivot()
character:PivotTo(currentPivot * CFrame.new(teleportTarget))
end
end
-- Llama a la función de teletransporte cuando el cliente activa el evento remoto
teleportEvent.OnServerEvent:Connect(teleportPlayer)

Lecturas de propiedades de instancias

Una vez que una instancia se transmite fuera, sus actualizaciones de propiedades ya no se replican a ese cliente. Leer propiedades como BasePart.Position continúa teniendo éxito pero devuelve el último valor replicado, que puede estar arbitrariamente desactualizado.

local Players = game:GetService("Players")
local player = Players.LocalPlayer
-- La posición puede estar desactualizada si "target" se ha transmitido fuera
local dist = (target.Position - player.Character.HumanoidRootPart.Position).Magnitude

Mueve la lógica al servidor, ya que los scripts del lado del servidor ven todas las instancias en todo momento. Esta es generalmente la opción más confiable para verificaciones de distancia y otra lógica sensible a la posición.

Esperando en la ruta crítica

Algunos juegos no streaming cargan su mapa clonándolo desde ReplicatedStorage en Workspace, luego esperan a que esté disponible en el cliente antes de despedir una pantalla de carga y señalar que están listos. Bajo streaming, esto se cuelga indefinidamente — el personaje del cliente aún no ha aparecido, por lo que no hay foco de replicación, y la instancia del mapa espacial nunca se transmite.

Mueve la lógica de la pantalla de carga para que no dependa de que una instancia espacial específica esté presente, por ejemplo, señalando que está lista una vez que el personaje ha aparecido y el área inmediata se ha transmitido.

Manejo de cambios de señal

Señales como Instance.ChildAdded/Instance.ChildRemoved y señales de CollectionService como GetInstanceAddedSignal() o GetInstanceRemovedSignal() también se activan en la transmisión dentro/fuera, indistinguibles de verdaderas apariciones/remociones. Los scripts receptores no pueden distinguir la diferencia solo por la señal, por lo que la lógica que asume que una señal corresponde a un evento "real" necesita ser actualizada.

Audita los scripts en busca de cualquier oyente de señales que pueda romperse o cambiar significativamente cuando se active por la transmisión dentro y/o fuera. Por ejemplo, si reproduces efectos de audio o visuales cuando un NPC enemigo aparece inicialmente en el mundo, asigna a cada enemigo un atributo como Spawned en la primera aparición, y omite la reproducción del mismo audio/efectos en futuras transmisiones del enemigo.

Seguimiento de Atributos
local CollectionService = game:GetService("CollectionService")
local TAG_NAME = "Enemy"
CollectionService:GetInstanceAddedSignal(TAG_NAME):Connect(function(enemy)
if not enemy:GetAttribute("Spawned") then
-- Establecer el atributo "Spawned" en el enemigo para la aparición inicial
enemy:SetAttribute("Spawned", true)
-- Reproducir efectos de audio/visual para esta aparición inicial
playSpawnEffects(enemy)
end
end)

Iteración sobre colecciones

Las iteraciones de colecciones del lado del cliente como Instance:GetChildren() y Instance:GetDescendants() devuelven solo el subconjunto transmitido de descendientes. Esto se aplica incluso cuando el padre en sí siempre se replica, como una Folder directamente bajo Workspace cuyos descendientes espaciales se transmiten dentro y fuera.

local Players = game:GetService("Players")
local player = Players.LocalPlayer
-- La carpeta "Homes" siempre se replica pero sus hijos se transmiten dentro y fuera
-- Este bucle puede perder hogares que no están actualmente transmitidos
for _, home in workspace.Homes:GetChildren() do
if home.Settings.Owner.Value == player.Name then
return home
end
end

Si se requiere una enumeración completa, realiza el escaneo en el servidor y pasa el resultado al jugador a través de un RemoteEvent si es necesario.

Consultas espaciales

Las consultas espaciales del lado del cliente como WorldRoot:Raycast(), WorldRoot:GetPartBoundsInBox(), y Model:GetBoundingBox() reflejan solo el contenido transmitido. Si eso es un problema depende de para qué se use la consulta.

Usa el servidor para consultas cuyo resultado debe reflejar el mundo completo, por ejemplo, un raycast que verifica si el jugador tiene línea de visión a un objetivo distante.

Otros patrones

Los siguientes patrones también pueden aplicarse y deben considerarse cuidadosamente:

  • Un Sound o AudioPlayer parentado a un objeto 3D se detiene cuando ese objeto se transmite fuera. Para audio ambiental que debe persistir independientemente del streaming, parenta el emisor a un modelo persistente o a un contenedor no streaming.

  • Objetos de UI en el juego como BillboardGui o SurfaceGui así como efectos visuales como Beams o Highlights cuyo adornee o adjunto se transmite fuera simplemente dejan de renderizarse. Este puede ser el comportamiento previsto, pero debes verificarlo.

  • Los eventos BasePart.Touched, ProximityPrompts, DragDetectors, y ClickDetectors no operan para jugadores cuyo cliente no tiene la parte/modelo asociado transmitido. Si la interacción debe ser posible desde cualquier rango, el modelo necesita ser persistente o la interacción necesita un mecanismo diferente.

  • Para PathfindingService y la búsqueda de caminos del lado del cliente, el buscador de caminos solo ve la geometría transmitida en el cliente y puede enrutarse a través de obstáculos que existen en el servidor. Consulta aquí para estrategias.

Condiciones de prueba realistas

Una vez que los scripts están actualizados, prueba el juego a fondo. Los errores de streaming a menudo solo se manifiestan en los bordes del área transmitida o durante transiciones, por lo que solo probar cerca de la aparición o en el radio objetivo no es suficiente.

  • Prueba con Workspace.StreamingTargetRadius establecido en su valor mínimo (64). Algunos errores de streaming solo aparecen cuando el área transmitida es pequeña.

  • Juega a través de los patrones de recorrido completos del juego, teletransportándote entre áreas distantes y revisitando áreas después de haberlas dejado. Estas son las situaciones que ejercen más el streaming dentro y fuera.

  • Usa la superposición de depuración de streaming para monitorear la configuración de streaming activa, las regiones actualmente cargadas y el estado de streaming en tiempo de ejecución.

  • Observa la ventana de Output y la Consola de Desarrollador en busca de errores, ya que muchos de los patrones de script producen errores en lugar de un comportamiento silencioso incorrecto. Presta especial atención a errores de la forma attempt to index nil with ... que a menudo indican una llamada faltante a WaitForChild().

  • Equipa y activa Tools, dispara armas y activa diferentes interacciones del juego.

Habilidad de conversión de streaming de IA

Para ayudar con la conversión y optimización de streaming, Roblox ofrece una habilidad de streaming de IA, accesible desde el servidor MCP de Studio. La habilidad evalúa automáticamente tu juego, aplica configuraciones recomendadas y limpia problemas de compatibilidad, incluyendo:


Para usar la habilidad de IA en tu juego:

  1. IMPORTANTE
    Haz una copia de seguridad de tu juego. El proceso de conversión puede ser complejo, así que siempre debes guardar una copia de seguridad (Archivo ⟩ Publicar en Roblox Como) antes de ejecutar la habilidad.

  2. Puedes ejecutar esta habilidad usando cualquier LLM que prefieras a través del Protocolo de Contexto de Modelo (MCP) en Studio. Se recomiendan modelos de IA de gama alta con grandes ventanas de contexto; en Claude Opus, la conversión típica toma de 20 a 30 minutos y utiliza aproximadamente 200,000 tokens de contexto.

    1. Abre tu juego en Studio.
    2. Descarga la habilidad y, en tu cliente de IA, abre la carpeta descomprimida (roblox-streaming-conversion) como el proyecto actual.
    3. Ejecuta la habilidad con /rbx-convert-to-streaming.
    4. Como con cualquier salida de IA, verifica los resultados y prueba tu juego extensivamente bajo condiciones de prueba realistas.
©2026 Roblox Corporation. Roblox, el logotipo de Roblox y "Powering Imagination" son algunas de nuestras marcas registradas y no registradas en los Estados Unidos y otros países.