unity3d
API CullingGroup
Поиск…
замечания
Поскольку использование CullingGroups не всегда очень просто, может оказаться полезным инкапсулировать основную часть логики класса менеджера.
Ниже приведен пример того, как может работать такой менеджер.
using UnityEngine;
using System;
public interface ICullingGroupManager
{
int ReserveSphere();
void ReleaseSphere(int sphereIndex);
void SetPosition(int sphereIndex, Vector3 position);
void SetRadius(int sphereIndex, float radius);
void SetCullingEvent(int sphereIndex, Action<CullingGroupEvent> sphere);
}
Суть в том, что вы резервируете сферу отбраковки от менеджера, который возвращает индекс зарезервированной сферы. Затем вы используете данный индекс для управления вашей зарезервированной сферой.
Отбор объектов
В следующем примере показано, как использовать CullingGroups для получения уведомлений в соответствии с контрольной точкой расстояния.
Этот сценарий был упрощен для краткости и использует несколько высокопроизводительных методов.
using UnityEngine;
using System.Linq;
public class CullingGroupBehaviour : MonoBehaviour
{
CullingGroup localCullingGroup;
MeshRenderer[] meshRenderers;
Transform[] meshTransforms;
BoundingSphere[] cullingPoints;
void OnEnable()
{
localCullingGroup = new CullingGroup();
meshRenderers = FindObjectsOfType<MeshRenderer>()
.Where((MeshRenderer m) => m.gameObject != this.gameObject)
.ToArray();
cullingPoints = new BoundingSphere[meshRenderers.Length];
meshTransforms = new Transform[meshRenderers.Length];
for (var i = 0; i < meshRenderers.Length; i++)
{
meshTransforms[i] = meshRenderers[i].GetComponent<Transform>();
cullingPoints[i].position = meshTransforms[i].position;
cullingPoints[i].radius = 4f;
}
localCullingGroup.onStateChanged = CullingEvent;
localCullingGroup.SetBoundingSpheres(cullingPoints);
localCullingGroup.SetBoundingDistances(new float[] { 0f, 5f });
localCullingGroup.SetDistanceReferencePoint(GetComponent<Transform>().position);
localCullingGroup.targetCamera = Camera.main;
}
void FixedUpdate()
{
localCullingGroup.SetDistanceReferencePoint(GetComponent<Transform>().position);
for (var i = 0; i < meshTransforms.Length; i++)
{
cullingPoints[i].position = meshTransforms[i].position;
}
}
void CullingEvent(CullingGroupEvent sphere)
{
Color newColor = Color.red;
if (sphere.currentDistance == 1) newColor = Color.blue;
if (sphere.currentDistance == 2) newColor = Color.white;
meshRenderers[sphere.index].material.color = newColor;
}
void OnDisable()
{
localCullingGroup.Dispose();
}
}
Добавьте скрипт в GameObject (в данном случае куб) и нажмите «Воспроизвести». Каждый другой объект GameObject в сцене меняет цвет в соответствии с их расстоянием до контрольной точки.
Очистка видимости объекта
Следующий сценарий иллюстрирует, как получать события в соответствии с видимостью для установленной камеры.
Этот сценарий для краткости использует несколько высокопроизводительных методов.
using UnityEngine;
using System.Linq;
public class CullingGroupCameraBehaviour : MonoBehaviour
{
CullingGroup localCullingGroup;
MeshRenderer[] meshRenderers;
void OnEnable()
{
localCullingGroup = new CullingGroup();
meshRenderers = FindObjectsOfType<MeshRenderer>()
.Where((MeshRenderer m) => m.gameObject != this.gameObject)
.ToArray();
BoundingSphere[] cullingPoints = new BoundingSphere[meshRenderers.Length];
Transform[] meshTransforms = new Transform[meshRenderers.Length];
for (var i = 0; i < meshRenderers.Length; i++)
{
meshTransforms[i] = meshRenderers[i].GetComponent<Transform>();
cullingPoints[i].position = meshTransforms[i].position;
cullingPoints[i].radius = 4f;
}
localCullingGroup.onStateChanged = CullingEvent;
localCullingGroup.SetBoundingSpheres(cullingPoints);
localCullingGroup.targetCamera = Camera.main;
}
void CullingEvent(CullingGroupEvent sphere)
{
meshRenderers[sphere.index].material.color = sphere.isVisible ? Color.red : Color.white;
}
void OnDisable()
{
localCullingGroup.Dispose();
}
}
Добавьте сценарий в сцену и нажмите «Играть». Вся геометрия в сцене изменит цвет, основываясь на их видимости.
Подобный эффект может быть достигнут с использованием
MonoBehaviour.OnBecameVisible()
если объект имеет компонентMeshRenderer
. Используйте CulingGroups, когда вам нужно отбросить пустые координаты GameObjects,Vector3
или когда вам нужен централизованный метод отслеживания видимости объектов.
Ограничительные расстояния
Вы можете добавить ограничивающие расстояния поверх радиуса точки высева. Они находятся в режиме дополнительных условий срабатывания вне основного радиуса точки выбраковки, например, «близко», «далеко» или «очень далеко».
cullingGroup.SetBoundingDistances(new float[] { 0f, 10f, 100f});
Ограничения расстояний влияют только при использовании с дистанционной контрольной точкой. Они не действуют во время отбраковки камеры.
Визуализация граничных расстояний
То, что может изначально вызвать путаницу, заключается в том, что ограничивающие расстояния добавляются поверх радиусов сферы.
Во-первых, группа выбраковки вычисляет площадь как ограничивающей сферы, так и граничного расстояния. Эти две области объединены вместе, и результатом является область триггера для диапазона расстояния. Радиус этой области может быть использован для визуализации поля действия ограничивающего расстояния.
float cullingPointArea = Mathf.PI * (cullingPointRadius * cullingPointRadius);
float boundingArea = Mathf.PI * (boundingDistance * boundingDistance);
float combinedRadius = Mathf.Sqrt((cullingPointArea + boundingArea) / Mathf.PI);