top of page
Foto del escritorBraulio Madrid

Qué es y cómo usar el Dynamic Occlusion



Introducción

En este blog aprenderemos a configurar mejor la herramienta de Dynamic Occlusion y usarlo en conjunto con la oclusión estática que viene por defecto en unity.


Qué es Dynamic Occlusion.

Oclusión en videojuegos es un término usado para el ocultamiento de objetos en tiempo real y se hace para ganar rendimiento. Dynamic occlusion es un asset de pago, que puedes encontrar en la tienda de unity aquí. Este asset nace en la Versión 3.5 de unity debido que la oclusión estática era una característica de pago, pero con el tiempo evolucionó a trabajar en conjunto con la oclusión estática y alcanzar a hacer el trabajo que este no cubre.


Dynamic Occlusion cuenta con varias características para la oclusión de varios objetos en varias situaciones distintas, para objetos en movimiento o para objetos poco convencionales. a parte de algunas opciones extras que mejoran el rendimiento.




Este asset viene principalmente con tres Scripts, DynamicOcclusionSystem.cs, DynamicLOD.cs y ClassExtensions.


Dynamic Occlusion: se encarga de ocultar o mostrar los objetos en pantalla, controlar la calidad de las luces, apagar o encender el audio 3D y controlar la calidad visual del juego para mantener el rendimiento.


Dynamic LOD: se encarga de hacer lo mismo que el sistema de detalles del unity, pero lo hace de manera más sencilla y automática, generando menos objetos que como lo hace unity.


Class Extension: Es una clase que tiene funciones necesarias, para que Dynamic LOD y Dynamic Occlusion funcionen correctamente, así que esta clase no se debe tocar.


Nota: Cabe destacar que Dynamic LOD y Dynamic Occlusion, dependen de la clase Mono Singleton, que solo permite sacar una sola copia a escena. además que ambos scripts no se permiten ser agregados múltiples veces en un mismo objeto.


Cómo Usar Dynamic Occlusion

Hay dos maneras en que puedes usarlo, la manera simple es arrastrando o agregandolo como componente a cualquier objeto deseado, pero preferiblemente que sea un objeto como la cámara principal o un game manager.


La otra manera es llamarlo desde otra script mediante código, por ejemplo:

private DynamicOcclusionSystem DOS;

void Start(){

DOS = Singletons.Get<DynamicOcclusionSystem>();

}


Hay otros modos de hacer este mismo llamado a la script, propios del asset Singletons de SqurePiStudios. dejaré más información en este link 

Este automáticamente creará un nuevo objeto en el que incluirá a Dynamic Occlusion System.



Cam: será la cámara que se usará para efectuar la oclusión. De no elegir ninguna, se seleccionará la main camera de la escena.


Camera DynamicOcclusion.cam;

Debug: Será el texto usado para ver cuántos objetos en escena son controlados actualmente por DOS.


Text DynamicOcclusion.text;

Tags: DOS busca todos los objetos que tengan estos tags y que no sean parte de Static Batch, y con ellas hace un listado que luego va a usar para activar y desactivar el componente Renderer.


List<string> DynamicOcclusion.tags;

Tags for Disable Game Object: DOS busca todos los objetos con estos tags y comprueba que no hagan parte del static Batch, para incluirlos en una lista que luego va a usar para desactivar o activar el objeto entero.


List<string> DynamicOcclusion.tagsForDisableGO;

Nota: esto es así porque a veces desactivar componentes a veces no es suficiente para ganar rendimiento. Se recomienda que solo se use esta opción en objetos que no tengan scripts que funcionan en tiempo real, porque podría provocar comportamientos no deseables en su proyecto.


Distances: hace uso de las distancias de las 32 capas en la cámara, hace uso de Camera.layerCullDistances esta opción se usa para desactivar objetos en la distancia, pero no tiene en cuenta el ocultamiento detrás de otros objetos. pero es una muy barata en rendimiento.


int[] DynamicOcclusion.distances;

Auto Quality: Activar esta opción funciona en conjunto con minimal y maximal FPS. Este permite bajar o subir la calidad de los gráficos, si su juego cae por debajo del valor mínimo o lo sube si su juego supera los FPS máximos.


bool DynamicOcclusion.autoQuality;

Terrain Quality: baja o sube la calidad del terreno dependiendo del rendimiento de los FPS, tambien depende de la opción minimal y maximal FPS.


bool DynamicOcclusion.terrainQuality;

Minimal & Maximal FPS: parámetros usados para AutoQuality y Terrain Quality, tiene un máximo de 60 FPS, porque esta script limita a 60 FPS usando Application.targetFrameRate si está activo la sincronización vertical. y esto se hace para mantener un rendimiento estable y ambos CPU y GPU trabajen de forma más descansada.


Fast Method: Unity por defecto usa la clase Frustum Planes

 si desea usar la opción por defecto, desactive esta opción. Frustum Planes es muy preciso, pero algo costoso.


Activando Fast Method, verifica la posición de objetos 3D si es visible en cámara. es una opción menos costosa pero puede desaparecer objetos muy grandes si el pivote sale de la cámara.


bool DynamicOcclusion.fastMethod

Renderers Occlusion: oculta todos los renderers, mesh renderers, skinned mesh renderer, line renderer, trail renderer, y particle renderers. siempre que no hagan parte de static batch. Si ve que hay objetos que se escapan de ser ocultados eso se debe a que son parte del static batch, comúnmente ocurre con las partículas.


bool DynamicOcclusion.renderersOcclusion;

Lights Occlusion: Este componente tiene algunas opciones extras que no hacen otros assets del mismo tipo.  en este caso mejora la calidad de las luces que estén en pantalla y reduce la calidad cuando estas salen de la cámara y las desactiva cuando estas están muy lejos.


bool DynamicOcclusion.lightsOcclusion;

Audio Source Occlusion: Otra característica especial para el audio en 3D, que permite desactivar el sonido si hay un obstaculo entre la camara y la fuente del sonido. mejorando la experiencia 3D y ahorrando memoria.


bool DynamicOcclusion.audioSourceOcclusion;

Flares Occlusion: aunque esta opción funciona bien con las colisiones, aún continúa funcionando y continúa activo, activar esta opción, permite desactivar definitivamente el componente. pero probablemente esta sea la opción menos utilizada, porque es poco lo que pueda mejorar.


bool DynamicOcclusion.flaresOcclusion;

Hide Behind: permite ocultar objetos detrás de otros, incluso si no contiene un collider. sin embargo puede generar comportamientos no deseados, como por ejemplo que un objeto grande sea ocultado por otro más pequeño.


bool DynamicOcclusion.hideBehind;


funciones públicas

Estas funciones tienen como objetivo actualizar las listas de objetos que deben ser administrados en el momento que lo necesitemos como por ejemplo, llamarlo después de haber generado objetos proceduralmente o después de una nueva oleada de enemigos o cada vez que se agrega una nueva escena de forma aditiva. etc.


public void ClearRenderersList(): borra los objetos en las listas. Generalmente usado antes de cambiar a una nueva escena.


public void UpdateRenderersList(): actualiza las listas con nuevos objetos de acuerdo a la configuración y los tags. Generalmente se usa después de haber borrado las listas de objetos.


public void FastConfiguration(): aplica una configuración rápida, llamando a todos los objetos necesarios.

Nota: Dynamic Occlusion puede mejorar el rendimiento notablemente pero también puede empeorarlo, todo va dependiendo del tamaño de los listados, por eso se recomienda que se use conjuntamente con static Occlusion y deje solo este para objetos en movimiento u objetos generados proceduralmente.


 

Cómo usar Dynamic LOD

Usar Dynamic LOD tiene ventajas sobre unity LOD, respecto a que hace lo mismo, sin generar objetos extras indeseables en escena, puede configurarse automáticamente ahorrando tiempo.


Su uso es similar al anterior, también tienes dos maneras de vincularlo a un objeto, la más simple arrastrando la script a un objeto.

y la segunda manera es haciendo un llamado a través de una script, por ejemplo:


private DynamicLOD dLOD;

void Start(){

dLOD = Singletons.Get<DynamicLOD>();

}


DynamicLOD.lodDatas[]: Lista que contiene cada uno de los componentes y distancias automáticas para hacer los cambios.


Mesh Filter: es el componente Mesh filter a manipular.

(meshFilter) DynamicLOD.lodDatas[x].meshFilter;

Lod 0: es el dato de la malla con mayor detalle.


(mesh) DynamicLOD.lodDatas[x].lod0;

Lod 1: es el dato de la malla con detalle mediano.


(mesh) DynamicLOD.lodDatas[x].lod1;

Lod 2: es el dato de la malla más bajo.


(mesh) DynamicLOD.lodDatas[x].lod2;

Automatic Distance: Activando esta opción, ignora los valores Lod Distance 1 & 2 y los asigna automáticamente de acuerdo al tamaño de la malla.

(bool) DynamicLOD.lodDatas[x].automaticDistance;


Mesh Renderer: se usa para determinar si es necesario hacer el cambio de malla o no de acuerdo a si es visible o no en cámara. y de acuerdo a la distancia en la que se encuentre el renderer de la cámara.


Cam: necesaria para hacer los cálculos, si no seleccionas nada. esta elegirá la main camera de la escena.

(Camera) DynamicLOD.cam;

Puedes agregar cada componente de forma manual, pero te tardarás media vida haciendo esto si tienes varios objetos. así que puedes hacer una script que haga esto automáticamente. puedes tomar ejemplo de los prefabs de la demo.


Cómo usar algunos trucos

he hecho esta imagen para explicar más fácilmente cómo actúa cada elemento respecto a la posición y visión de la cámara



Los elementos a tener en cuenta son las tres áreas, far clipping planes, frustum y game object deactivation. los objetos interactúan en estas 3 áreas y el dominio de estas áreas hará que pongas a punto tu rendimiento y el funcionamiento de los objetos. también teniendo en cuenta que no todos los géneros de videojuegos funcionana de la misma manera.


Cuando diseñé el sistema lo hice pensado en un juego de aventuras en tercera persona, esto no quiere decir que no pueda funcionar en otros géneros.


Sonido: Es muy simple de controlar, los audioSources tienen el parámetro Spatial blend que va de 0 a 1, siendo 0 un sonido totalmente 2D, preciso para efectos de interfaz o música de fondo, y siendo 1 el sonido totalmente en 3D.


Si quieres que un sonido determinado sea controlado por dynamic Occlusion, desplaze el Spatial blend a 1, esto permitirá que la prioridad del sonido cambie respecto a la distancia y cambie respecto al ocultamiento de los objetos, produciendo una sensación similar a como actuaría el sonido en la realidad.


Si deseas tener sonidos que no estén controlados por DOS, pero aun asi sea sonido 3D, pon el Spatial blend a 0,9f, de esta manera mantendrá la prioridad en el punto original.


Luces: DOS no deshabilita la iluminación, solo cambia la forma en que los renderiza dependiendo de si se encuentran dentro del frustum de la cámara y dependiendo si hay algún objeto que obstaculice la emisión de la luz y la cámara si tiene activada la opción Hidden Behind, tenga en cuenta que DOS no afecta a la luz direccional. también es recomendable que si la fuente de luz está estática, opte por un horneado de luces en lo posible.


Si usted desea que por algún motivo alguna luz se represente de una manera concreta y que esta no sea tenida en cuenta por DOS, puede marcar el objeto como estático si realmente es estático, o cambie el Tag del objeto por cualquiera que no esté incluida en la lista de DOS.


Renderers: Este es el punto más complejo y en el que hay que poner más atención. recuerde que DOS trata a todos los renderers de la misma forma y esto incluye, Mesh Renderers, SkinnedMesh Renderers, Trail Renders, Line Renderer, y Particle System Renderers. tenga en cuenta que el tratamiento de los objetos depende mucho del volumen de este y quizás tenga interés en otros métodos de oclusión diferentes al convencional.


Generalmente los objetos más incómodos de tratar sean los objetos de mayor volumen, pero también hay que tener en mente como se presentará ese objeto dentro de su juego. daré algunos ejemplos posibles.


Supongamos que su personaje principal se está enfrentando a una criatura gigantesca (algo del tamaño de un dinosaurio, un kraken, un nyarlathotep) que lo persigue y se atraviesan objetos constantemente. Quizás desactive momentáneamente la opción de Hidden Behind porque puede producir parpadeos a esta criatura gigantesca, y quizás desactive la opción Fast Method, para que cuando el volumen salga de la cámara no lo haga tan abruptamente.


Podría considerar poner a esta criatura gigantesca con un tag que DOS no controle y dejando el resto de opciones como estaban inicialmente, teniendo en cuenta que esta criatura solo aparece momentáneamente en escena.


Supongamos que el juego sea del tipo RTS donde ves hordas de soldados, quizás desactivar la opción hidden behind tenga más sentido ya que usted desea ver un volumen de soldados, sin embargo usted aún desea que se beneficien del rendimiento al salir de la cámara.


Supongamos que ahora su juego sea un walking simulator que genera paisajes aleatoriamente en cada partida, pero que no pueda beneficiarse del rendimiento estático por alguna razón. aún está la opción de cull Layer Distances y poner los objetos en distintas capas según su volumen, porque pueda aun permitirse usar capas. ademas que DOS puede usar esta opción de forma más barata.


Supongamos que usted tenga unos objetos que no pueden ser estáticos porque usen físicas que solo de activan en un momento concreto, pero que su rol no sea muy importante. puede usar la opción GO Deactivation para ganar rendimiento drásticamente.


Cómo ve estos son algunos ejemplos complejos que se me ocurren y la manera de solucionarlo, puede presentarse muchas más situaciones, pero DOS es lo suficientemente versátil para hacerle frente a distintos problemas. 


Conclusión

Mantenga en mente que una buena optimización resulta de una estricta planeación y a pesar de que con orgullo he creado tan maravilloso asset, he de reconocer que mi conocimiento en rendimiento ahora es tan elevado que DOS solo me sirve como cinturón de castidad pero aun sigue siendo mi amigo fiel a pesar de todo.


Hacer uso shaders que te permite compartir materiales y efectos mas simples que simulan lo mismo que un montón de partículas, reciclar objetos de un pool, o hacer uso de las herramientas que posee el mismo unity, sabiendo medir las consecuencias me ha permitido reducir un montón de memoria, envíos de dibujado y DOS ha estado siempre para cuidar de las cosas no he planeado.


Con esto quiero decirle que si usted no es muy obsesivo como yo lo soy, Dynamic Occlusion System es perfecto para usted, lo animo a que aprenda siempre más.

21 visualizaciones0 comentarios

Comments


bottom of page