Ricerca…


Osservazioni

Poiché usare CullingGroups non è sempre molto semplice, può essere utile incapsulare la maggior parte della logica dietro una classe manager.

Di seguito è riportato un modello su come un simile gestore potrebbe operare.

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

L'essenza di ciò è che si riserva una sfera di abbattimento dal manager che restituisce l'indice della sfera riservata. Quindi usi l'indice dato per manipolare la tua sfera riservata.

Individuazione delle distanze dell'oggetto

L'esempio seguente illustra come utilizzare CullingGroups per ottenere notifiche in base al punto di riferimento della distanza.

Questo script è stato semplificato per brevità e utilizza diversi metodi pesanti per le prestazioni.

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

Aggiungi lo script a un GameObject (in questo caso un cubo) e premi Riproduci. Ogni altro oggetto GameObject nella scena cambia colore in base alla loro distanza dal punto di riferimento.

inserisci la descrizione dell'immagine qui

Cogliendo la visibilità dell'oggetto

Il seguente script illustra come ricevere eventi in base alla visibilità di una telecamera impostata.

Questo script utilizza diversi metodi di prestazioni pesanti per brevità.

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

Aggiungi lo script alla scena e premi Riproduci. Tutte le geometrie nella scena cambieranno colore in base alla loro visibilità.

inserisci la descrizione dell'immagine qui

Un effetto simile può essere ottenuto usando il metodo MonoBehaviour.OnBecameVisible() se l'oggetto ha un componente MeshRenderer . Usa CulingGroups quando hai bisogno di selezionare GameObjects vuoti, coordinate Vector3 o quando vuoi un metodo centralizzato per monitorare la visibilità degli oggetti.

Distanze limite

È possibile aggiungere distanze di limitazione in cima al raggio del punto di smistamento. Sono in un certo modo condizioni di innesco aggiuntive al di fuori del raggio principale dei punti di abbattimento, come "vicino", "lontano" o "molto lontano".

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

Le distanze limite influiscono solo quando usate con un punto di riferimento della distanza. Non hanno alcun effetto durante l'eliminazione della telecamera.

Visualizzazione delle distanze limite

Ciò che inizialmente potrebbe causare confusione è il modo in cui le distanze di limitazione vengono aggiunte sopra i raggi della sfera.

Innanzitutto, il gruppo di selezione calcola l' area sia della sfera di delimitazione che della distanza di delimitazione. Le due aree vengono sommate e il risultato è l'area di innesco per la banda di distanza. Il raggio di quest'area può essere usato per visualizzare il campo d'effetto della distanza di delimitazione.

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
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow