Version: 2020.2
Sparse Textures (Texturas Dispersas)
Loading texture and mesh data

CullingGroup API

El CullingGroup ofrece una manera de integrar sus propios sistemas al pipeline LOD y al culling de Unity. Esto puede servir a varios propósitos; por ejemplo:

  • Simular una multitud de personas, mientras que solamente los personajes que están visibles en el momento tienen GameObjects completo.
  • Construir un sistema de partículas del GPU manejado por Graphics.DrawProcedural, al omitir el renderizado de sistemas de partículas que están detrás de una pared
  • Hacerle seguimiento a qué puntos de generación (spawn) están ocultos de la cámara con el fin de generar enemigos sin que el jugador los vea ‘aparecer’ en la vista
  • Cambiar los personajes de una animación de alta calidad y cálculos de AI cuando estén cerca, a un comportamiento más ‘barato’ de baja calidad en la distancia
  • Tener 10,000 puntos marcadores en su escena y eficientemente averiguar cuándo un jugador llega a 1m de cualquiera de ellos

The API works by having you provide an array of bounding spheres. The visibility of these spheres relative to a particular camera is then calculated, along with a ‘distance band’ value that can be treated like a LOD level number.

Empezando con CullingGroup

No hay componentes o herramientas visuales para trabajar con CullingGroups; estas son puramente accesibles vía script.

Un CullingGroup se puede construir utilizando el operador ‘new’:

CullingGroup group = new CullingGroup();

Para que el CullingGroup realice cálculos de visibilidad, especifique la cámara que debe utilizar:

group.targetCamera = Camera.main;

Create and populate an array of BoundingSphere structures with the positions and radii of your spheres, and pass it to SetBoundingSpheres along with the number of spheres that are actually in the array. The number of spheres does not need to be the same as the length of the array. Unity recommends that you create an array that is big enough to hold the most spheres you will ever have at one time, even if the initial number of spheres you actually have in the array is very low. Using a larger array allows you to add or remove spheres as needed without the computationally expensive process of resizing the array at runtime.

BoundingSphere[] spheres = new BoundingSphere[1000];
spheres[0] = new BoundingSphere(Vector3.zero, 1f);
group.SetBoundingSpheres(spheres);
group.SetBoundingSphereCount(1);

En este punto, el CullingGroup va a empezar a calcular la visibilidad de una sola esfera cada frame.

Para limpiar el CullingGroup y librar toda la memoria que utiliza, elimine el CullingGroup vía el mecanismo estándar .NET IDisposable:

group.Dispose();
group = null;

Receiving results via the onStateChanged callback

La manera más eficiente de responder al cambio de visibilidad de las esferas o el estado de distancia es utilizar el campo para el callback onStateChanged. Configure esto a una función que toma una estructura CullingGroupEvent como un argumento; luego será llamado después de que el culling haya sido completado, para cada esfera que ha cambiado de estado. Los miembros de la estructura CullingGroupEvent le dice a usted acerca de los estados previos y nuevos de la esfera.

group.onStateChanged = StateChangedMethod;

private void StateChangedMethod(CullingGroupEvent evt)
{
    if(evt.hasBecomeVisible)
        Debug.LogFormat("Sphere {0} has become visible!", evt.index);
    if(evt.hasBecomeInvisible)
        Debug.LogFormat("Sphere {0} has become invisible!", evt.index);
}

Receiving results via the CullingGroup Query API

Adicionalmente al delegate onStateChanged, el CullingGroup proporciona un API para recuperar los últimos resultados de visibilidad y distancia de cualquiera esfera en el arreglo de las esferas que delimitan. Para revisar los estados de una sola esfera, utilice los métodos IsVisible y GetDistance:

bool sphereIsVisible = group.IsVisible(0);
int sphereDistanceBand = group.GetDistance(0);

Para revisar los estados de varias esferas, usted puede utilizar el método QueryIndices. Este método escanea un rango continuo de esferas para averiguar las que coinciden una visibilidad dada o estado de distancia.

// Asigne una matriz para contener los índices de esfera resultantes: el tamaño de la matriz determina las esferas máximas comprobadas por llamada
int[] resultIndices = new int[1000];
// También configure un int para almacenar el número real de resultados que se han colocado en la matriz
int numResults = 0;

// Encuentra todas las esferas que son visibles.
numResults = group.QueryIndices(true, resultIndices, 0);
// Encuentra todas las esferas que están en la banda de distancia 1
numResults = group.QueryIndices(1, resultIndices, 0);
// Encuentra todas las esferas que están ocultas en la banda de distancia 2, saltándose las primeras 100
numResults = group.QueryIndices(false, 2, resultIndices, 100);

Recuerde que la información recuperada por el API de consultas solamente se actualiza cuando la cámara utilizada por el CullingGroup en realidad realiza su culling.

Mejores prácticas del CullingGroup API

Cuando considere cómo aplicar el CullingGroup a su proyecto, considere el siguiente aspecto del diseño del CullingGroup.

Utilizando visibilidad

Todos los volúmenes para ver qué CullingGroup calcula la visibilidad están definidos por las esferas que delimitan - en práctica, una posición (el centro de la esfera) y un valor de un radio. Ningún otra forma que delimita está soportada, por razones de rendimiento. En práctica esto significa que usted definirá una esfera que completamente encierre el objeto que es de su interés para el culling. Si un encaje más ajustado se necesita, considere utilizar varias esferas para cubrir diferentes partes del objeto, y tomar decisiones basado en el estado de visibilidad de todas las esferas.

Con el fin de evaluar visibilidad, el CullingGroup necesita saber desde qué cámara la visibilidad será calculada. Actualmente un solo CullingGroup soporta una sola cámara. Si usted necesita evaluar la visibilidad de varias cámaras, debería utilizar un CullingGroup por cámara y combinar los resultados.

El CullingGroup calcula la visibilidad basado en el frustum culling y la occlusion culling estática solamente. No tomará los objetos dinámicos en cuenta como oclusores potenciales.

Utilizando la distancia

El CullingGroup es capaz de calcular la distancia enter algún punto de referencia (por ejemplo, la posición de la cámara o el jugador) y el punto más cercano en cada esfera. Este valor de distancia no se le proporciona directamente a usted, pero en vez es cuantificado utilizando un conjunto de valores de umbral que usted proporciona, con el fin de calcular un ‘distance band’(banda de distancia) discreto de tipo entero como resultado. La intención es que usted interprete estas distance bands como ‘close range’ (rango cercano), ‘medium range’ (rango mediano), ‘far range’ (rango lejano), y así.

El CullingGroup va a proporcionar callbacks cuando un objeto se mueve de estar en una banda a estar en otra, dándole a usted la oportunidad de hacer cosas como cambiar el comportamiento de ese objeto a algo menos intensivo al CPU.

Any spheres that are beyond the last distance band will be considered to be invisible, allowing you to easily construct a culling implementation that completely deactivates objects that are very far away. If you do not want this behaviour, simply set your final threshold value to be at an infinite distance away.

Solo un punto de referencia es soportado por CullingGroup.

Rendimiento y diseño

El CullingGroup API no le da a usted la habilidad de realizar cambias a su escena y luego solicitar inmediatamente el nuevo estado de visibilidad de la esfera que delimita. Por razones de rendimiento, el CullingGroup solo calcula información nueva de visibilidad durante la ejecución del culling para la cámara completa; es en este punto que la información está disponible para usted, ya sea vía un callback, o vía el CullingGroup API de consultas. En práctica, esto significa que usted debería acercarse al CullingGroup de una manera asincrónica.

El arreglo de las esferas de-limitantes que usted proporciona al CullingGroup es referenciado por el CullingGroup, en vez de ser copiado. Esto significa que usted debe mantener una referencia al arreglo que usted pase a SetBoundingSpheres, y que pueda modificar los contenidos de este arreglo sin necesidad de llamar SetBoundingSpheres nuevamente. Si usted necesita que haya varios CullingGroups que calcule la visibilidad y las distancias para el mismo conjunto de esferas - por ejemplo, para varias cámaras - entonces es eficiente tener que todos los CullingGroups compartan la misma instancia de las esferas de-limitantes.

Sparse Textures (Texturas Dispersas)
Loading texture and mesh data