Suche…


Bemerkungen

Da die Verwendung von CullingGroups nicht immer sehr unkompliziert ist, kann es hilfreich sein, den Großteil der Logik hinter einer Manager-Klasse zu kapseln.

Nachfolgend finden Sie einen Plan, wie ein solcher Manager funktionieren kann.

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);
}

Das Wichtigste dabei ist, dass Sie eine Sperrkugel vom Manager reservieren, die den Index der reservierten Kugel zurückgibt. Sie verwenden dann den angegebenen Index, um Ihre reservierte Kugel zu manipulieren.

Entfernungen von Objekten abschneiden

Das folgende Beispiel veranschaulicht die Verwendung von CullingGroups zum Abrufen von Benachrichtigungen anhand des Entfernungsreferenzpunkts.

Dieses Skript wurde aus Gründen der Kürze vereinfacht und verwendet mehrere Methoden, die die Performance stark beeinträchtigen.

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();
    }
}

Fügen Sie das Skript einem GameObject (in diesem Fall einem Cube) hinzu, und klicken Sie auf Spielen. Jedes andere GameObject in der Szene ändert seine Farbe entsprechend der Entfernung zum Referenzpunkt.

Geben Sie hier die Bildbeschreibung ein

Objektsichtbarkeit aussortieren

Das folgende Skript veranschaulicht, wie Ereignisse entsprechend der Sichtbarkeit einer festgelegten Kamera empfangen werden.

Dieses Skript verwendet aus Gründen der Kürze mehrere leistungsstarke Methoden.

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();
    }
}

Fügen Sie das Skript der Szene hinzu und klicken Sie auf Wiedergabe. Alle Geometrie in der Szene ändert ihre Farbe entsprechend ihrer Sichtbarkeit.

Geben Sie hier die Bildbeschreibung ein

Ein ähnlicher Effekt kann mit der MonoBehaviour.OnBecameVisible() Methode erzielt werden, wenn das Objekt eine MeshRenderer Komponente hat. Verwenden Sie CulingGroups, wenn Sie leere GameObjects-, Vector3 Koordinaten Vector3 oder eine zentralisierte Methode zum Verfolgen von Objektsichtbarkeiten verwenden möchten.

Begrenzte Entfernungen

Sie können Begrenzungsabstände über dem Radius der Auslagerungspunkte hinzufügen. Sie sind in gewisser Weise zusätzliche Auslösebedingungen außerhalb des Hauptradius der Sammelpunkte wie "nah", "weit" oder "sehr weit".

cullingGroup.SetBoundingDistances(new float[] { 0f, 10f, 100f});

Begrenzungsentfernungen wirken sich nur bei Verwendung eines Entfernungsbezugspunkts aus. Sie haben keine Auswirkungen während des Kamera-Ausschlusses.

Begrenzungsabstände visualisieren

Was anfangs für Verwirrung sorgen kann, ist, wie Begrenzungsabstände über den Kugelradien hinzugefügt werden.

Zunächst berechnet die Culling-Gruppe die Fläche sowohl der Begrenzungssphäre als auch der Begrenzungsentfernung. Die beiden Bereiche werden addiert und das Ergebnis ist der Triggerbereich für das Entfernungsband. Der Radius dieses Bereichs kann verwendet werden, um das Wirkungsfeld der Begrenzungsentfernung zu visualisieren.

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
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow