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.

wprowadź opis zdjęcia tutaj

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.

wprowadź opis zdjęcia tutaj

Podobny efekt można uzyskać za pomocą metody MonoBehaviour.OnBecameVisible() , jeśli obiekt ma składnik MeshRenderer . Korzystaj z CulingGroups, gdy potrzebujesz zabić puste obiekty GameObjects, współrzędne Vector3 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);


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow