Cómo optimizar el mapa del mundo abierto de Unity
Esquema de carga de datos de terreno grande
Teniendo en cuenta el mecanismo de memoria existente, la carga de terreno grande no se puede agregar a la memoria a la vez. De hecho, este problema es obvio en el juego. A menudo nos encontramos con esto en el desarrollo, como nuestra barra de progreso común. El propósito de cargar la barra de progreso es esperar a que el programa cargue la escena. Para cargar terrenos grandes, no hay otra forma que usar fragmentación. Esta es la dirección general, por lo que, como programa, lo que hay que hacer es cómo fragmentarlo. ¿Cuál es el tamaño del bloque? Necesitamos dividir estos problemas específicos según nuestras necesidades. Por ejemplo, el tamaño del bloque del simulador de vuelo puede ser mayor porque la perspectiva de vista es relativamente grande, el bloque itinerante de la escena puede ser más pequeño, etc. A continuación, usaremos el clásico. game-Warcraft Tomemos como ejemplo el esquema de carga del terreno mundial para presentar su principio de implementación a los lectores. El juego World of Warcraft realiza la unión de mapas sin fisuras, por lo que es de gran valor de referencia. p>
¿Cómo consigue World of Warcraft mapas infinitos? De hecho, también se compone de muchos bloques de escena. Analizamos la división de tamaño de los bloques de terreno de World of Warcraft a través del editor. La escena de World of Warcraft que llamamos MapWorld se compone de una serie de MapTiles. 1600/3 ≈ 533,33 m, y cada MapTile se compone de 16x16 MapChunk, a partir del cual se puede calcular cada MapChunk≈33,33 m. Luego, cada MapChunk es una textura de superficie compuesta por alturas de vértice de terreno de 9x9 + 8x8, normales y varias capas de textura (generalmente 4 capas). No discutiremos aquí el tamaño del terreno de World of Warcraft, pero podemos aprender de su idea de dividirlo en bloques.
Continúe analizando el método de bloqueo de World of Warcraft: se dividen según el método matricial y se realizan en el plano XZ. Cada bloque contendrá ciertos datos de información, por ejemplo: en XZ (. 3, 3) Ubicación MapTile, cada MapTile contiene las texturas, instancias de modelo, etc. utilizadas en el mosaico. Las llamadas instancias de modelo son nuestros accesorios, que pueden entenderse como información sobre las diferentes posiciones de ubicación, tamaños y ángulos del mismo modelo en el mosaico. Todos se guardan en archivos binarios para ahorrar tamaño de archivo. Las instancias del modelo se pasan a través del modelo de índice y se guardan de manera similar al índice de vértice. También hay información de textura en cada MapTile, como el nombre de la textura y la información UV, etc. El método de pensamiento en bloques de este curso es similar al de World of Warcraft, que se presentará en detalle en capítulos posteriores. Una vez divididos los bloques, el siguiente es el principio de implementación.
Principio de implementación: en cualquier momento, el programa siempre guarda MapTiles 3x3 donde está el jugador y alrededor de él, a medida que el jugador se mueve, estos MapTiles se actualizarán dinámicamente y se cargarán nuevos MapTiles para reemplazarlos. Se desinstaló el antiguo MapTile. Para mejorar la eficiencia de la programación, Warcraft introduce un mecanismo de caché que almacena hasta 16 datos de MapTile. Cuando es necesario cargar un nuevo MapTile, primero se buscará en la caché; el MapTile antiguo desinstalado no se eliminará inmediatamente, sino que se guardará en la caché para volver a llamarlo. Dado que el rango de actividad del jugador generalmente no cambia mucho durante un período de tiempo, esta estrategia de caché funciona muy bien en la aplicación. Este es el principio básico de los mapas integrados. Usaremos subprocesos múltiples para implementar la carga y descarga dinámica de terreno. Integraremos dos subprocesos: un subproceso está dedicado a cargar terreno y el otro subproceso está dedicado a descargar u ocultar MapTiles del terreno. Recordemos nuevamente el juego clásico. El efecto de la escena del juego es el siguiente:
El método implementado en este curso puede utilizar dos métodos para abordar el problema de carga y visualización de bloques. El método del grupo de objetos, carga previamente el terreno parchado, detecta y determina qué parcelas mostrar y qué parcelas ocultar en función de la distancia de visión, pero no se eliminan aquí. Esto sólo requiere un hilo. Otra forma es utilizar subprocesos múltiples y configurar un subproceso específicamente para eliminar y descargar gráficos que no están a la vista. Esto puede mejorar la eficiencia. El esquema de carga que utiliza subprocesos múltiples se presenta a continuación.
Subprocesos múltiples para implementar una solución de carga de terreno grande
El subproceso múltiple se usa a menudo en juegos de PC. Por ejemplo, se puede dedicar un subproceso a cargar recursos. en servidores de juegos Con respecto al uso de subprocesos múltiples, a continuación se presenta el plan de implementación de subprocesos múltiples a los lectores. El problema del procesamiento de subprocesos múltiples es poner toda la lógica de carga en un nuevo proceso y realizar alguna comunicación entre procesos. El hilo principal, acepta las sugerencias de carga del hilo principal y realiza la carga bajo demanda. También realizará una precarga por adelantado y la colocará en la memoria asignada, al igual que World of Warcraft. A través del mecanismo de intercambio de memoria entre procesos, el terreno cargado. Los datos se compartirán con todos. El proceso principal del juego siempre solo necesita mantener una pequeña memoria, y una gran cantidad de datos de la memoria se procesa en otro proceso. De esta manera, se puede optimizar la carga de bloques de terreno grandes. El método de implementación es el siguiente:
Primero, el hilo principal cargará nueve bloques de terreno y el hilo principal solo es responsable de mantener estos nueve. bloques de terreno No importa cómo se mueva el personaje, dónde está el personaje. El área completa siempre son nueve piezas de terreno. Como se muestra en la figura anterior, estas nueve piezas se pueden cargar directamente en la memoria usando el hilo principal. 16 piezas en el caché a través de otro hilo. La posición del personaje está en el medio de las nueve piezas de terreno que se han cargado, que es donde está A. A medida que el personaje se mueve, se agregarán nuevos bloques de terreno y se reemplazarán los bloques de terreno existentes. De esta manera, siempre se mostrarán nueve bloques de terreno. El terreno reemplazado no se descargará inmediatamente y se procesará de acuerdo con el movimiento de. el personaje Pre-juicio, esperará la notificación del hilo principal y descargará y cargará tramas de acuerdo con ciertas reglas. De hecho, este método de implementación es lo que normalmente llamamos tecnología de doble caché y subprocesos múltiples. El efecto logrado es el siguiente:
Después de cargar el terreno en fragmentos, debemos considerar el problema del mapa de textura en el terreno. Los recursos del mapa de textura del terreno también ocuparán una gran cantidad de memoria. Aquí se explica cómo cargar cantidades masivas de memoria.
Esquema de carga para imágenes masivas de terrenos grandes
Hay muchas imágenes de escena en terrenos grandes. Habrá al menos cuatro capas de texturas en el terreno que debemos considerar al cargar. Tantas texturas, también debemos considerar estos factores al dividirnos en bloques. Además, también debemos considerar el horneado LightMap utilizado en la escena para aliviar la presión de la memoria, empaquetaremos los materiales del terreno y los materiales de construcción. En diferentes bloques de antemano, primero introduzcamos cómo cargar texturas de escena en fragmentos. La forma en que se implementa es la siguiente:
La idea es escribir las texturas de la escena en diferentes atlas según los bloques que dividimos. Por supuesto, las texturas de los dos bloques también se pueden escribir. un atlas. El tamaño máximo del álbum para PC es 4096 y el máximo para dispositivos móviles es 2048. Esto también es para evitar la carga y descarga frecuente de memoria, lo que provocará una gran fragmentación de la memoria, lo que no favorece la asignación posterior de una gran cantidad de memoria. Lo que debemos hacer antes de crear el atlas es establecer una correspondencia uno a uno entre los mapas de textura en los bloques de terreno y nuestro atlas empaquetado para facilitar la comparación. Debido a que no habrá relación entre el atlas que empaquetamos y el terreno real, para establecer la correspondencia entre los dos necesitamos crear otra tabla de archivos de índice entre ellos, que es el puente que conecta el atlas y la textura del terreno real, a través del. archivo de índice que construimos, podemos encontrar la correspondencia entre las texturas en el terreno real y las texturas del atlas. La tabla de índice que construimos se cargará en la memoria y nuestro atlas se agregará más tarde de acuerdo con la tarea de carga. memoria, lo que requiere que tengamos la menor cantidad de archivos de índice posible, porque residen en la memoria. Además de cargar imágenes masivas, también debemos manejar la carga de edificios intensivos.
- Esquema de carga para edificios densos
Carga de edificios densos, imagínese, si todos los edificios en la escena se cargan en la memoria a la vez, la memoria se llenará en un instante La velocidad de cuadros cae instantáneamente, razón por la cual todos se congelan cuando se encuentran con edificios densos mientras se mueven en la escena del juego. El método de procesamiento anterior era usar procesamiento LOD y usar modelos simplificados para objetos ocluidos. Esto también aumentará la carga en la memoria. Si el personaje sigue yendo y viniendo entre edificios, es necesario cambiar diferentes modelos LOD. lo cual también es una carga para la memoria, el efecto no es ideal.
Estos problemas deben ser resueltos por los programadores. Mucha gente piensa en fusionar mallas grandes. Este método no funciona. Las mallas grandes no son adecuadas para operaciones de recorte. Imagine que la cámara que fusionamos solo ve una pequeña parte de las mallas porque son un todo. memoria juntos, pero de hecho no necesitamos tantos datos del modelo al fusionar cuadrículas, aquí hay una sugerencia para los lectores que intenten fusionar modelos que estén muy cerca entre sí para evitar los problemas anteriores. De hecho, la solución más efectiva es dividir los bloques en bloques. Esta división de bloques se puede realizar utilizando la idea de división del terreno. Está estrechamente relacionado con los bloques de terreno que se cargan. junto con los bloques de terreno. Si los edificios en el bloque son muy densos, este método no puede resolverlo por completo y se necesita un procesamiento adicional, que consiste en agregar el algoritmo de oclusión OC combinado con el algoritmo LOD, para que nuestro problema actual también se pueda resolver por completo. El tema de este curso
El método que se explicará y el método de optimización adicional es colocar el algoritmo de oclusión OC y el algoritmo LOD en la GPU para su cálculo, de modo que se mejore la eficiencia. Un artículo GPU. -Driven Rendering Pipelines se publicó en Siggraph2015. Su idea es utilizar la GPU para el procesamiento de oclusión y recorte, que se divide principalmente en dos etapas. Utiliza la API de gráficos DX12, como se muestra en la siguiente figura:
La primera etapa, la fase amplia, encuentra rápidamente una lista de posibles. pares de objetos de colisión Aquellos que no están en esta lista son absolutamente imposibles de colisionar. La fase amplia identifica un lote de pares de objetos que requieren una inspección adicional.
La segunda fase, fase estrecha, encuentra con precisión la lista de pares de objetos que colisionaron. Debido a que algunos pares de objetos en la etapa anterior en realidad no chocaron, es necesario eliminarlos en esta etapa.
Existe un algoritmo simple en la fase amplia llamado barrido y poda (SAP), que esencialmente utiliza un algoritmo de clasificación. El primer paso es inicializar la lista de clasificación. Los elementos de la lista son cuadros delimitadores, que se pueden completar utilizando cualquier algoritmo de clasificación, como la clasificación rápida. La clasificación posterior no utilizará la clasificación rápida, sino la clasificación por burbujas. más útil? Esto se debe a una premisa predeterminada: el movimiento de los objetos tiene coherencia temporal, es decir, las posiciones del cuadro actual y el cuadro siguiente están cerca, por lo que durante el proceso de clasificación de burbujas, se espera que los intercambios de posición que ocurren sean muy cercanos. .
De hecho, hay muchas similitudes en los algoritmos. Aquí también debemos aprender de las ideas de resolución de problemas de los demás para resolver nuestros problemas. El autor solía trabajar en juegos de PC y muchas de las ideas de optimización de los juegos de PC también son aplicables al terminal móvil. En comparación con el terminal de PC, el terminal móvil es solo una computadora con una configuración relativamente baja. Luego continuamos presentando nuestro recorte de oclusión a los lectores. El autor del artículo también realizó una prueba de eficiencia, tomando como ejemplo 250.000 objetos y una cuadrícula de 1G. Los resultados de la prueba son los siguientes:
¿No es genial? Se puede utilizar para resolver problemas en el desarrollo de proyectos. Hablemos sobre el uso de GPU para optimizar nuestras escenas de terreno grande.
Solución de optimización de renderizado de terrenos grandes de GPU
Nuestros terrenos grandes primero tendrán su propio mapa de superficie. El mapa de superficie comúnmente utilizado es la fusión de cuatro texturas, y se pueden combinar hasta ocho texturas. fusionado, la representación de la textura del terreno implicará el algoritmo LOD. La cuadrícula del terreno distante se puede simplificar y la textura correspondiente también es la más baja. Además, debe haber hierba, flores y una gran cantidad de otros objetos idénticos para renderizar. Hablemos primero del dibujo de hierba y flores. Habrá muchos de ellos en el juego. parche proporcionado por el motor o la cruz, o tres imágenes Cruz, y luego asigne la textura con el canal Alfa, como se muestra en la siguiente figura:
Está bien que la CPU dibuje esta hierba. o flores en el lado de la PC, porque las computadoras de hoy son multinúcleo. La versión móvil afectará los problemas de eficiencia.
Cuando se usa la CPU para dibujar, habrá muchos DrawCalls y será necesario mover la hierba o las flores, lo que requiere muchos cálculos, lo que afecta seriamente la eficiencia operativa. Si la CPU tiene dificultades, la GPU puede ayudar. Podemos poner el dibujo de hierba o flores en la GPU. Cuando se ejecuta, el efecto es el siguiente: