Saltar al contenido principal

Por qué este motor

No es una lista de funciones, sino el puñado de decisiones que cambian lo que puedes construir, y por qué importan en la práctica.

Un solo modelo, en todas partes

El editor, el reproductor web, la app del móvil y el servidor ejecutan la misma escena: los mismos objetos, los mismos componentes, el mismo comportamiento.

No hay paso de exportación, ni un «formato de ejecución» aparte, ni una segunda implementación que se desvíe de la primera. Lo que colocaste en el editor es lo que corre, y un fallo que ves en el reproductor se reproduce en todas partes.

La consecuencia práctica es aburrida y valiosa: las cosas no cambian de significado al publicar.

Los grafos se convierten en código, no en un intérprete

En la mayoría de las herramientas, un grafo visual es un dato que algo recorre en ejecución, nodo a nodo, en cada fotograma. Aquí se compila a un script normal, una vez, y ese script es lo que corre.

Velocidadun grafo cuesta lo mismo que el código escrito a mano, porque es código
Inspeccionableabre el panel de código y lee exactamente en qué se convirtió tu grafo
Componibleun grafo puede llamar a un script y un script a un grafo, porque por debajo son lo mismo

Así que no hay un techo en el que tengas que abandonar la herramienta visual y reescribirlo todo en código. Añades un script junto al grafo que ya tienes.

Los materiales son grafos hasta el fondo

Los tipos de material integrados no son un conjunto cerrado con un editor de nodos atornillado. Son puntos dentro del mismo sistema que usa un grafo propio, así que un material en grafo no es más lento, ni un ciudadano de segunda, ni está limitado a la web: el mismo grafo compila para el navegador y para el renderizador nativo de un móvil.

Y lo que no usas no cuesta nada. Los extras físicos que se quedan en sus valores por defecto se pliegan en tiempo de compilación, así que un material con la opción de ser vidrio es exactamente igual de barato que uno sin ella.

Funciona como una hoja de cálculo

Esta es la decisión sobre la que se apoya todo lo demás, y lo más fácil es explicarla con una analogía.

En una hoja de cálculo cambias una celda y solo se recalculan las fórmulas que usan esa celda. Nadie recalcula la hoja entera, y nunca pulsas un botón de «actualizar».

La escena funciona exactamente así. Cambia el color de un objeto y lo único que reacciona es lo que estaba leyendo el color. No el objeto: el color.

cambio  material.color

├─ el renderizador repinta esa superficie
├─ el campo del inspector que lo muestra se actualiza
├─ el cambio se pone en cola para tus colaboradores
└─ …y no se ejecuta nada más

Qué te da eso

Nada sondea y nada se rerenderiza por si acaso. No hay una pasada por fotograma que compare el mundo con una copia de sí mismo para averiguar qué se ha movido. Un fotograma hace el trabajo que exigen los cambios, y una escena quieta no cuesta casi nada.

Las escenas grandes siguen respondiendo mientras las editas. Una línea de tiempo con veinte mil keyframes no se redibuja porque uno se haya movido: un panel puede depender de «los keyframes han cambiado» sin suscribirse a cada keyframe de la lista. Esa distinción es lo que mantiene usables los proyectos grandes.

Cargar no necesita código de carga. Un sistema pide un recurso y no recibe nada si aún no ha llegado; cuando llega, el sistema simplemente se vuelve a ejecutar. Nadie escribe callbacks, ni sondea una bandera de «listo», ni maneja dos veces el caso de «todavía no cargado».

Un único flujo de cambios alimenta todo. El renderizador, el inspector, deshacer, tus colaboradores, el sandbox de scripts y la simulación física leen las mismas actualizaciones, que es por lo que no pueden separarse ni discrepar sobre lo que contiene la escena. Deshacer no es un camino especial: es un cambio más pasando por la misma tubería.

No puedes olvidarte de avisar al motor. No hay «marcar como sucio», ni «refrescar», ni invalidación manual que recordar. Escribir el valor es la notificación.

Y las escrituras se hacen con cuidado

Actualizar un valor lo fusiona con lo que ya hay en vez de reemplazarlo, así que todo lo que estaba mirando sigue enganchado a lo mismo que miraba. Suena a detalle de implementación; es la diferencia entre una animación fluida y unos fotogramas por segundo que se hunden según crece tu escena.

No es una función del framework: es el sustrato

La reactividad es un paquete propio, y el mismo está a tu disposición. Un panel de plugin, una extensión de componente y el propio inspector del editor están escritos contra él, así que una extensión que escribas se actualiza exactamente por el mismo motivo que los paneles integrados.

import { signal, computed, effect, batch } from '@was/signals';

const score = signal(0);
const label = computed(() => `Score: ${score.value}`);

effect(() => render(label.value)); // se reejecuta solo cuando se mueve la puntuación
batch(() => { score.value += 1; score.value += 1; }); // una actualización, no dos

Merece la pena nombrar tres propiedades, porque la mayoría de los sistemas reactivos tienen una o dos:

De grano finolas dependencias se siguen por valor leído, no por componente. Nada se rerenderiza «por si acaso».
Profundaun árbol de objeto entero se vuelve reactivo, así que vigilar position.y no es vigilar el objeto
Barata de dependerpuedes depender de que algo cambió sin leerlo, que es lo que evita que una lista enorme se rerenderice cuando se mueve un elemento

Lo último suena arcano y es la razón por la que una línea de tiempo de veinte mil keyframes sigue siendo editable.

Los paquetes compartidos

Validación que no te cuesta un fotograma

Cada componente se describe con un esquema, y los esquemas normalmente significan un impuesto: algo recorre una descripción en ejecución, campo a campo, cada vez que llegan datos.

Aquí el esquema se compila una vez a código para esa forma exacta. No hay recorrido. La diferencia no es académica: medido con el propio banco de pruebas de este proyecto:

AnálisisAñadido al bundle
La biblioteca habitual (zod)94,7 ns por operación+267 KB minificados, +61 KB con gzip
Esta (svdt)5,0 ns por operaciónnada: ya está ahí

Unas diecinueve veces más rápido, y nada extra que descarguen tus visitantes.

Importa porque aquí la validación no es un suceso raro: corre en cada cambio que cruza entre el editor, el sandbox de scripts, la simulación física y tus colaboradores. Un coste por campo que parece insignificante se convierte en el presupuesto de animación cuando ocurre miles de veces por segundo.

Tú también lo tienes

Es el mismo paquete que tu propio plugin puede importar para sus propios datos. → Los paquetes compartidos

El trabajo pesado se queda fuera del fotograma

Dos cosas que normalmente atascan una página de navegador se sacan de ella:

  • Tus scripts corren aislados de la página, así que un bucle lento no puede congelar el renderizado.
  • La física corre junto al fotograma, no dentro de él.

Una escena sigue respondiendo mientras está ocupada, en lugar de perder fotogramas cuando tu lógica se pone interesante.

El runtime se niega a trabajar hasta que lo necesita

Esta es la parte que se manifiesta como tiempo de carga para tus visitantes.

La física no arranca, ni se descarga, a menos que una escena la necesite de verdad. Un decorado sin partes móviles nunca paga por el simulador, y eso son megabytes que tus visitantes no esperan. La comprobación está viva: una pelota creada a mitad de sesión levanta la física por su cuenta.

Diez mil copias cuestan más o menos una. La hierba, las multitudes, los escombros y las partículas se dibujan en una sola llamada. Su disposición se genera a partir de una semilla en vez de guardarse, así que no cuesta nada en el archivo, nada en la red, y se ve idéntica para cada participante.

Nada a nivel de partícula se sincroniza jamás. Los mismos ajustes producen el mismo efecto en todas partes, así que un efecto elaborado sale gratis en multijugador.

Un solo vocabulario para el comportamiento

Eventos, grafos de patch y scripts oyen los mismos disparadores: on-click significa lo mismo en los tres. Aprendes un juego de nombres y luego eliges cuánto código quieres escribir.

Eso también significa que puedes empezar una interacción como evento, ascenderla a patch cuando necesite una condición, y pasarte a un script cuando necesite lógica de verdad, sin volver a aprender nada.

Construido para más de una persona

La colaboración no es una función atornillada encima: un space es un mundo vivo compartido por todos los que están dentro, así que las ediciones aparecen según ocurren y deshacer funciona por persona.

La misma maquinaria sincroniza el editor, el sandbox de scripts y la simulación física, que es por lo que no pueden discrepar sobre lo que contiene la escena.

Corre donde tu público ya está

Un proyecto publicado se abre desde un enlace, en un navegador, sin nada que instalar. De eso va la WebAR: sin tienda de aplicaciones, sin descarga, sin «instala primero nuestra app» entre tu visitante y lo que has hecho.

A partir de ahí, el mismo proyecto llega más lejos sin reconstruirse:

DóndeCómo llega ahí
Cualquier navegador de móvilel enlace publicado, o un código QR: nada que instalar
App Clip de iOSse abre desde un enlace, un QR o NFC, sin instalar desde la App Store
La app nativaun renderizador nativo — ver abajo
Navegadores de visoresel mismo enlace publicado: el runtime habla WebXR
Gafas y visores ARuna capa XR nativa para XREAL One, Quest 3 y PICO 4 — ver abajo
Visores vía Unityel SDK de Unity — XREAL, PICO, Apple Vision Pro, HoloLens 2, Magic Leap 2, Rokid
Los App Clips son el camino más corto de un cartel a tu contenido

Alguien apunta la cámara a un código y tu experiencia se abre: sin tienda, sin cuenta, sin esperas. Apple limita el tamaño de un clip, así que mantén ligera la primera escena y carga el resto una vez esté en marcha.

Las compilaciones para visores mediante el SDK de Unity son un extra Enterprise

Los móviles funcionan de serie. Los paquetes específicos de cada dispositivo —pipelines de renderizado, perfiles de mando, plantillas de despliegue— se conceden por cuenta. → Plataformas soportadas

En un móvil, velocidad de renderizado nativa

En un navegador tienes WebGL: rápido y con techo. La app nativa no renderiza a través de un navegador en absoluto: usa un renderizador nativo tanto en iOS como en Android, hablando directamente con Metal y Vulkan.

Así que el mismo proyecto obtiene el presupuesto gráfico de una app nativa —sombras en tiempo real, materiales más pesados, más cosas en pantalla— sin que tengas que mantener una segunda versión. Tus materiales compilan para ese renderizador igual que para la web, que es lo que hace que «el mismo proyecto» sea cierto y no una aspiración.

Usa la compilación web por alcance, y la app para los proyectos que necesiten el presupuesto de fotograma.

Gafas, de forma nativa

Una capa XR nativa pone el propio runtime de AR Clip en unas gafas: el mismo proyecto, la misma escena, renderizada en el dispositivo y no en un navegador.

Está construida como una única interfaz con backends de fabricante intercambiables, así que un dispositivo es un backend y no una bifurcación del runtime, y no pasa por Unity:

DispositivoA través deQué funciona ahí
XREAL Oneel SDK del fabricantepantalla, seguimiento de cabeza, cámara, grabación de sesión
Meta Quest 3OpenXRpantalla, seguimiento, mandos, seguimiento de manos, grabación de sesión
PICO 4OpenXRlo mismo, con la cámara desactivada
Las capacidades cambian según el dispositivo, y el runtime te dice cuáles hay

Un backend declara lo que realmente admite en vez de fingir. PICO aquí no tiene paso de cámara, así que una escena que necesite el mundo real detrás pertenece a XREAL o a Quest; una que no lo necesite corre en las tres.

Venga por donde venga un visitante, es la misma escena con los mismos componentes y el mismo comportamiento. No estás manteniendo una versión web y una versión para visor.

Y es ampliable en los sitios que importan

Tus propios pasos y disparadores se pueden registrar desde una aplicación. El editor admite plugins que añaden paneles, generan escenas o aportan clases de componente enteramente nuevas. El catálogo de nodos tiene una salida de emergencia para el único caso que no cubre.

Por qué esta documentación no se queda vieja

Todas las tablas de componentes, disparadores, pasos y nodos de este sitio se generan desde el propio motor. Cuando el motor gana un nodo, la referencia gana una fila: nadie tiene que acordarse de actualizarla.


Siguiente: Objetos y escenas — el modelo completo.