Cómo ECS, C # Job System y SRP cambian la arquitectura

Hemos estado trabajando con Unity durante mucho tiempo y no pudimos evitar invitar a sus muchachos a Pixonic DevGAMM Talks, que fue en septiembre. El ingeniero de campo Valentin Simonov dijo cómo planificar la arquitectura de los juegos teniendo en cuenta las ventajas de las nuevas tecnologías. Unity ha estado trabajando en ellos durante varios años para lograr un nivel de rendimiento previamente inalcanzable. Puede escuchar la presentación en YouTube y leer la transcripción con diapositivas justo debajo del corte.


¿Qué pasa si digo que puedes aumentar la productividad de tu juego 10 veces? De hecho, esto no es del todo cierto, pero hay algo de verdad en cada broma. Quiero hablar sobre en qué estamos trabajando ahora, cuál será el futuro de Unity y qué puede usar ahora.

La unidad hace juegos completamente diferentes. Aquí hay algunos ejemplos que juego yo mismo. Utilizan diferentes funciones y necesitan un rendimiento diferente, un enfoque diferente para el desarrollo.



Y estamos trabajando en un proyecto que llamamos Rendimiento por defecto. Estas son algunas características especiales que, si se usan correctamente, lograrán un aumento significativo del rendimiento. En algunas tareas, medimos x10 e incluso x11. Especialmente en los problemas de simulación de una gran cantidad de objetos que interactúan entre sí.

Pero cuando hablamos de Perfomance por defecto, queremos decir que tendrá que cambiar el enfoque del desarrollo, cambiar en gran medida el enfoque de la arquitectura de los juegos. Y, de hecho, no todos necesitan esto.

Una pregunta popular: “¿Qué estás haciendo en tu ECS? ¿Eliminas todo GameObject, eliminas toda Transformación, jerarquía y componentes? No, todos lo dejamos. Puede trabajar con Unity exactamente igual que ahora, pero si desea obtener más rendimiento, debe conocer brevemente las tecnologías de las que quiero hablar.

Y quiero mencionar otra tecnología llamada Scriptable Render Pipelines (SRP): le permite escribir de manera más eficiente una tubería de renderizado para su juego. Probablemente viste la demostración que mostramos en uno de Unite. Aquí en PC en tiempo real, se simula un número gigante de unidades, alrededor de 60 mil (llega a 100 mil y comienza a disminuir un poco):


Y las nuevas características de las que quiero hablar son: Entity Component System (ECS), C # Job System, nuestro nuevo supercompilador Burst y Scriptable Render Pipelines (SRP).



Repito: depende de ti elegir si quieres seguir adelante con nosotros, aprender nuevas tecnologías o si estás de acuerdo en desarrollar juegos que ganen dinero y que simplemente se hagan.

Para entender lo que estamos tratando de resolver, es importante comprender el estado del hierro en 2018.



Observe cómo crece el rendimiento y la cantidad de núcleos de CPU. Desde un punto, el rendimiento de un solo hilo incluso se redujo. Es decir, ahora tenemos muchos núcleos, pero su productividad no está creciendo tan rápido. Por lo tanto, nos gustaría utilizar el poder de todos los núcleos.



Mi teléfono tiene 8 núcleos: 4 fuertes y 4 débiles. Y un teléfono moderno puede funcionar tan rápido como una computadora moderna (pero no mucho tiempo debido al sobrecalentamiento). También debe comprender que aumentar el rendimiento no solo utiliza todos los núcleos, sino que también optimiza el rendimiento de un solo núcleo.

Y la última imagen, que siempre damos como ejemplo de cómo aumenta el rendimiento del proceso y la velocidad de acceso a la memoria no aumenta tanto:



Se puede ver que ahora el acceso a la memoria es extremadamente lento. Los fabricantes de procesadores hacen mucho para nivelar esta diferencia: agregan cachés, las CPU se dedican al cálculo especulativo, tratando de predecir qué código se ejecutará a continuación. Y si no piensas en ello cuando haces tu juego (o cuando hacemos un motor para ti), entonces no podemos aprovechar al máximo los procesadores modernos.

Es probable que muchos de ustedes pasen horas mirando una imagen similar en Unity:



Aquí puede ver que hay subprocesos múltiples, pero los núcleos y subprocesos restantes no están ocupados. Se está haciendo algo, pero me gustaría ocuparlos por completo.

Ahora tenemos renderizado, este es un cuadro negro. Tiene una opción: Reenviar o Diferir, además de varias configuraciones para materiales, sombreadores, Buffers de comandos, etc. Puede hacer una imagen hermosa, pero muchos algoritmos son extremadamente difíciles de implementar.



Y todos sabemos acerca de la arquitectura en Unity: componentes, GameObjects, jerarquía de transformaciones, todo el código, todos los datos en MonoBehaviour y cada componente procesa sus datos.



Pero hay problemas con el estado actual de las cosas. Tarde o temprano te encuentras con esto y entiendes cómo necesitas y no necesitas hacerlo. La jerarquía de los objetos en sí tiene una cierta sobrecarga, y algunas entidades no tienen que ser GameObjects en absoluto. Y si tiene una gran cantidad de componentes y actualizaciones de ellos, entonces todo se vuelve mucho más lento. Una vez escribí este artículo , que sigue siendo relevante si quieres saber cómo no hacerlo.



Y lo más importante en el contexto de los procesadores es que todos los componentes, todos los datos están dispersos en la memoria, lo que interrumpe el uso de la memoria caché del procesador.

Ahora quiero pasar rápidamente por nuevas funciones.



No me enfocaré mucho en lo que es ECS y cómo funciona. El punto es que tenemos Entity, que es solo la identificación de ciertas entidades en el juego: almacenan datos en forma de componentes, es decir, solo datos, sin código. Y los sistemas procesan la Entidad con ciertos componentes y de alguna manera cambian estos datos.

¿Por qué estamos haciendo nuestro ECS y cómo será mejor que la competencia? Hay algunos puntos. Primero, no del todo oficialmente, pero creemos que haríamos el motor ahora. Está claro que no queremos deshacernos de GameObjects, los componentes actuales de Unity, desechar todo por completo e instalar ECS. Pero queremos avanzar hacia un mejor motor.



Contamos con alto rendimiento. No hace mucho tiempo, Mike Acton se unió a nosotros (si está en desarrollo de C ++, sabe que es uno de los evangelistas de la programación orientada a datos). Y queremos que todo el sistema funcione lo más rápido posible, más rápido que C ++.

También pensamos en cómo integrar diferentes cosas de forma nativa en ECS. Hace algún tiempo, anunciamos que estábamos creando una nueva red y también se basa en ECS: será posible hacer un juego multijugador en ECS y compartir código entre el cliente y el servidor.

Trabajando en herramientas de depuración en Unity. Es decir mientras que ECS existe, por así decirlo, por separado de GameObjects y componentes, y esto es muy inconveniente. Queremos simplificar las cosas.

Ahora hay un DebugView que se parece a esto:



Aquí puede ver qué tipo de entidad tiene, qué sistemas cuánto tiempo lleva procesar, qué sistemas funcionan con qué componentes y para cada componente que puede ver en el inspector, qué datos tiene cada entidad en los componentes (noto que la API a menudo cambia y muchos Los tutoriales ya pueden estar desactualizados).

Además, si escuchaste sobre nuestro nuevo desarrollo Unity for Small Things (este es un tiempo de ejecución muy pequeño que te permite crear juegos para mensajería instantánea), todo también está construido en ECS allí.

Recientemente, el auge del desarrollo y la transición a ECS es una tecnología muy popular y todos deben saberlo.

Tenemos una conferencia para programadores, por lo que es difícil prescindir de una diapositiva de código. Hay mucho código allí, por lo que es difícil extraer algún tipo de pieza inteligible para dejar algo claro.



De hecho, tomé un sistema del ejemplo que funciona con el Sistema de trabajo C # (más sobre eso más adelante), y hacemos mucho para reducir la cantidad de código, agregar una sintaxis shugar.

Hay un sistema que funciona con componentes RotationData y también necesita transformaciones de GameObject, que están representadas por un TransformAccessArray especial. Y cada actualización del sistema que creamos Job, ejecuta este Job, se actualiza en algún lugar, puede dividirse en varios grupos y ejecutarse en diferentes hilos.

¿Cómo usar en el proyecto? Al igual que en otras implementaciones de ECS, debe comprender que tiene que pensar de una manera completamente diferente (a diferencia de GameObjects y Transforms). Y acostumbrarse a esta idea. Está claro que debe comenzar desde el principio del proyecto, porque a menudo recibo preguntas como "hicimos el juego y queremos cambiar a ECS, ¿cómo?". En el juego terminado, esto es muy difícil de hacer.



Necesitamos pensar a través de la interacción con Unity, ya que ECS vive por separado, en su pequeño mundo. Brindamos algunas oportunidades de interacción con GameObjects y Transforms, pero la física, el renderizado, etc., aquí se vuelve cada vez más complicado. Y si bien debe soportar el hecho de que gran parte de la interfaz familiar no estará disponible, también estamos trabajando en esto.

E inmediatamente debe pensar en el hecho de que escribirá sistemas en el Sistema de trabajos, que es mucho más eficiente.



Algunas palabras sobre Job System. Queremos hacer una forma muy simple de escribir código multiproceso. Al mismo tiempo, escriba en C #, verifique todo por usted, no le dé la oportunidad de cometer errores ni muestre por qué, dónde y cómo los cometió. Limitamos las funciones de idioma que puede usar en Jobs y llamamos a este subconjunto C # High Performance C #. No tiene referencias en su código de trabajo, ni líneas, todos los datos deben copiarse; no puede usar una gran cantidad de funciones de idioma, lo que hace que sea mucho más difícil disparar múltiples hilos en su pierna.

También presentamos colecciones e integración muy rápidas con ECS. Esta estructura ECS y Job System permite una ejecución de código muy rápida.

Al mismo tiempo, no solo le brindamos la oportunidad de utilizar estas tecnologías, sino que también trabajamos con estos sistemas y creamos nuevas API para que puedan utilizarse en Jobs.



Hicimos Async Raycasts para física, con lo que puedes decir "Quiero 600 rakecasts, házmelo algún día, por favor". Estamos trabajando para garantizar que, utilizando estas tecnologías, sea posible expandir los sistemas actuales, por ejemplo, la animación a través de la API de Playbles. Y estamos pensando en hacer nuevos sistemas en Unity que no se cerrarán en C ++, y cuyo código estará en C # y disponible para usted.



Si toma el código de Job, es bastante simple. Job es una estructura en la que existe un método Execute, en el que hacemos algo de trabajo al ejecutar este Job. En consecuencia, nuestro Programador interno algún día comprenderá dónde es mejor ejecutarlo, resolverá todas las dependencias. Aquí obtenemos un JobHandle, que podemos usar como dependencia para otros trabajos.

¿Cómo usar en el proyecto? Es bueno que use Jobs desde el principio, pero esto no es necesario aquí. Si tiene algún tipo de sistema de rendimiento crítico, por ejemplo, simulaciones, búsqueda de rutas, redes u otra cosa, puede descubrir cómo optimizarlo con esta herramienta.



Pero para esto, debe dar algunos pasos importantes, comprender cómo almacenar datos correctamente. ECS, de hecho, nos permite almacenar datos correctamente, porque separamos los datos del código y nuestra implementación de ECS almacena los datos de los componentes linealmente en la memoria y, al ejecutar estos componentes por algún sistema, utiliza todas las capacidades del procesador, todo se almacena en la memoria caché y etc. Intentamos hacerlo muy rápido.

Luego divide este trabajo en tareas paralelas, escribe el código del trabajo y ejecútelo. Y (probablemente) todo funciona para ti. Por supuesto, debe probar y, lo más importante, probar en la plataforma de destino, dependiendo de la cantidad de núcleos, etc. Pero el uso de Job System y ECS, como dije, también afecta en gran medida la forma en que planifica la arquitectura de su juego.

Entonces todo es mucho más simple. Burst Compiler es nuestra tecnología única, un compilador especial de esta subred C # (High Performance C #) en el código de máquina de la plataforma actual, que publicará en su proyecto.



Los chicos hicieron algo de magia que probablemente nadie excepto ellos entienden, pero esto acelera el código de Job 10 veces, lo cual es súper genial. Y lo mejor es que no requiere ninguna acción por su parte: si tiene un código de trabajo, simplemente agregue el atributo [BurstCompile], Burst compila su código y obtiene un rendimiento "libre". Esta es nuestra nueva tecnología y puede probarla ahora.



Y lo último que quiero mencionar brevemente es el Scriptable Render Pipeline (SRP), en el que hemos estado trabajando durante mucho tiempo y que está diseñado para darle la oportunidad de escribir una representación muy personalizada para su juego específico.



Render Pipeline es un algoritmo que hace Culling (qué objetos se dibujarán), Rendering y Postprocesamiento. Ahora tenemos una caja negra, que reenvía o difiere: ya son buenos, obtenemos gráficos geniales en teléfonos móviles, PC y consolas. Pero tienen muchas restricciones, porque no se pueden ampliar. Con esta nueva función, SRP, puede escribir su Pipeline, puede eliminar algo de allí, agregar, hacer lo que quiera.



Actualmente estamos trabajando en dos ejemplos de tuberías. Un LWRP, al que apuntamos en teléfonos móviles y dispositivos débiles, y HDRP, al que apuntamos en PC, consolas, y en el que trabajan personas muy famosas de la industria. Antes de eso, hicieron juegos AAA. Seguramente, viste nuestra demo Libro de los muertos.


Aquí usamos HDRP para mostrar la potencia total de esta tecnología.

Para usar esto, también deberá tomar una cantidad bastante grande de pasos heroicos, porque con el nuevo Pipeline, casi nada es compatible con lo que tenemos ahora. Es decir si actualiza con Legacy, le brindamos una utilidad que actualizará la mayoría de los materiales por usted, pero deberá reescribir sus sombreadores, es decir las texturas probablemente se verán diferentes.



Muy bueno si puedes comenzar desde cero y experimentar con tu Pipeline. Si desea hacer algo en su tubería, contáctenos.

Nuevamente, comprenda lo que necesita, porque ahora tiene más oportunidades para hacer algo, pero necesitará personas que puedan hacerlo o tendrá que aprender cómo hacerlo.



En mi opinión, esto es genial, porque aquellos que sigan adelante con nosotros con estas nuevas tecnologías tendrán más demanda en el mercado. Eso es todo, espero que alguien vaya y vea estas tecnologías, haga juegos hermosos y geniales.

Preguntas de la audiencia


- ¿Cuándo puedo obtener ECS y desarrollarlo?

- Puede usar ECS, el problema es que, en su forma actual, está más dirigido a personas que se centran en el rendimiento, es decir algún tipo de proyecto AAA. Y la tarea de Unity es hacer que Performance by Default esté disponible para todos. Por lo tanto, necesitamos un cierto sistema, un complemento de ECS, que nos permita usar ECS con la misma facilidad con la que usamos MonoBehavior ahora. Si bien no existe tal complemento, no creo que ECS se lanzará en una versión completa. Y resulta que creamos una función que utilizará el 1% de nuestros usuarios. Y esta no es una tarea de Unity. Conozco personas que ya usan ECS en la producción, solo tengan en cuenta que esta característica aún está en desarrollo y ahora estamos resolviendo la cuestión de cómo hacer la interfaz más conveniente. Y la siguiente tarea (no menos difícil) es cómo hacer algún tipo de API que esté por encima de este ECS y le permita usarlo con la misma facilidad que MonoBehaviour. Es decir no hay respuesta a la pregunta "cuándo exactamente".

- ECS y el resto de los elementos se centran en tomar un GameObject básico y hacer 150 mil de sus clones y administrarlos. Pero, ¿qué pasa si tengo pocos objetos, pero tienen entidades diferentes?

- En principio, no puedes hacer nada, esta tecnología no te obliga a usarla. Si puede obtener un aumento de rendimiento utilizando estas tecnologías, debe usarlas. Si esto no es relevante para usted, entonces continúa utilizando Unity tal como está. Por lo tanto, no se asuste.

- Tenemos un cliente en Unity, un servidor en .NET, probamos un servidor en Unity, no sale nada. Pero al mismo tiempo, también quiero usar las tecnologías que están en Unity en el servidor.

- Estamos trabajando en esto y entendemos que ahora no podemos proporcionar una solución de servidor efectiva. Compramos la compañía Multiplay hace algún tiempo para crear hosting de alta calidad para juegos de Unity. Hacemos redes por separado y estamos comprometidos por separado a optimizar el motor para que se puedan sacar más cosas de él. En consecuencia, cuando todo se junta, tendremos una excelente solución multijugador.

Más conversaciones con Pixonic DevGAMM Talks


Source: https://habr.com/ru/post/es427359/


All Articles