unity3d
CullingGroup API
Szukaj…
Uwagi
Ponieważ korzystanie z CullingGroups nie zawsze jest bardzo proste, pomocne może być hermetyzowanie całej logiki stojącej za klasą menedżera.
Poniżej znajduje się plan działania takiego menedżera.
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);
}
Istotą tego jest to, że rezerwujesz kulę ubojową od menedżera, który zwraca indeks zarezerwowanej sfery. Następnie używasz podanego indeksu do manipulowania zarezerwowaną sferą.
Odległości obiektów ubijających
Poniższy przykład ilustruje sposób korzystania z CullingGroups, aby otrzymywać powiadomienia zgodnie z punktem odniesienia odległości.
Skrypt ten został uproszczony dla zwięzłości i wykorzystuje kilka metod wymagających dużej wydajności.
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();
}
}
Dodaj skrypt do GameObject (w tym przypadku kostki) i naciśnij Graj. Co drugi obiekt GameObject w scenie zmienia kolor zgodnie z odległością do punktu odniesienia.
Widoczność obiektów ubijających
Poniższy skrypt ilustruje sposób odbierania zdarzeń zgodnie z widocznością ustawionej kamery.
W tym skrypcie zastosowano kilka metod, które wymagają dużej wydajności.
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();
}
}
Dodaj skrypt do sceny i naciśnij Odtwórz. Cała geometria w scenie zmieni kolor w zależności od ich widoczności.
Podobny efekt można uzyskać za pomocą metody
MonoBehaviour.OnBecameVisible()
, jeśli obiekt ma składnikMeshRenderer
. Korzystaj z CulingGroups, gdy potrzebujesz zabić puste obiekty GameObjects, współrzędneVector3
lub gdy chcesz scentralizowaną metodę śledzenia widoczności obiektów.
Odległości graniczne
Możesz dodać odległości graniczne na szczycie promienia punktu uboju. Są one w pewnym sensie dodatkowymi warunkami wyzwalania poza głównym promieniem punktów uboju, takie jak „blisko”, „daleko” lub „bardzo daleko”.
cullingGroup.SetBoundingDistances(new float[] { 0f, 10f, 100f});
Odległości ograniczające mają wpływ tylko wtedy, gdy są używane z punktem odniesienia odległości. Nie mają one wpływu podczas ubijania kamery.
Wizualizacja odległości granicznych
To, co może początkowo powodować zamieszanie, to sposób dodawania odległości granicznych na wierzchołkach promieni kuli.
Najpierw grupa wybijania oblicza obszar zarówno kuli ograniczającej, jak i odległości ograniczającej. Oba obszary są sumowane, a wynikiem jest obszar wyzwalania dla pasma odległości. Promień tego obszaru można wykorzystać do wizualizacji ograniczającego pola odległości zasięgu.
float cullingPointArea = Mathf.PI * (cullingPointRadius * cullingPointRadius);
float boundingArea = Mathf.PI * (boundingDistance * boundingDistance);
float combinedRadius = Mathf.Sqrt((cullingPointArea + boundingArea) / Mathf.PI);