Search Unity

Culling group bug?

Discussion in 'Scripting' started by Alex1337rus, Dec 27, 2018.

  1. Alex1337rus

    Alex1337rus

    Joined:
    Mar 30, 2016
    Posts:
    37
    Hi! I am using culling group api and have some problems.
    1. I have a line of cubes.
    2. Camera moving along this line.
    3. When a cube is visible it has green color, else red color.
    4. While the camera moving it remove cubes.
    If the camera only moving without deleting - all visible cubes are green. With deleting some cubes are red.



    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class RenderManager : MonoBehaviour
    7. {
    8.     private Camera _camera;
    9.     private InstancedDrawObject[] items;
    10.     public GameObject prefab;
    11.     private Vector3 pos;
    12.     private Vector3 increment;
    13.  
    14.  
    15.     private CullingGroup cullingGroup;
    16.     private int usedBoundingSphereCount;
    17.     private BoundingSphere[] boundingSphere;
    18.     private InstancedDrawObject[] drawInstances;
    19.  
    20.     const int maxInstances = 250;
    21.  
    22.     private void Awake()
    23.     {
    24.         _camera = Camera.main;
    25.         drawInstances = new InstancedDrawObject[maxInstances];
    26.         boundingSphere = new BoundingSphere[maxInstances];
    27.  
    28.         InitializeCullingGroup();
    29.         InitializeItems();
    30.     }
    31.  
    32.     private void InitializeItems()
    33.     {
    34.         increment = new Vector3(50, 0, 0);
    35.    
    36.         items = new InstancedDrawObject[maxInstances];
    37.         int z = 35;
    38.  
    39.         for (int x = 0; x < maxInstances; ++x)
    40.         {
    41.             GameObject gameObject = Instantiate(prefab);
    42.  
    43.             InstancedDrawObject instancedDrawObject = gameObject.GetComponent<InstancedDrawObject>();
    44.             instancedDrawObject.position = new Vector3(x, 0, z);
    45.  
    46.             items[x] = instancedDrawObject;
    47.  
    48.             AddInstance(instancedDrawObject);
    49.         }
    50.  
    51.         pos = new Vector3(0, 0, z);
    52.     }
    53.  
    54.     private void InitializeCullingGroup()
    55.     {
    56.         cullingGroup = new CullingGroup();
    57.         cullingGroup.targetCamera = _camera;
    58.         cullingGroup.onStateChanged = CullingStateChanged;
    59.         cullingGroup.SetBoundingSpheres(boundingSphere);
    60.         usedBoundingSphereCount = 0;
    61.         cullingGroup.SetBoundingSphereCount(usedBoundingSphereCount);
    62.     }
    63.  
    64.     private void CullingStateChanged(CullingGroupEvent evt)
    65.     {
    66.         drawInstances[evt.index].visible = evt.isVisible;
    67.     }
    68.  
    69.     public void AddInstance(InstancedDrawObject instance)
    70.     {
    71.         drawInstances[usedBoundingSphereCount] = instance;
    72.         boundingSphere[usedBoundingSphereCount].position = instance.position;
    73.         boundingSphere[usedBoundingSphereCount].radius = instance.radius;
    74.  
    75.         ++usedBoundingSphereCount;
    76.         cullingGroup.SetBoundingSphereCount(usedBoundingSphereCount);
    77.         instance.visible = cullingGroup.IsVisible(usedBoundingSphereCount - 1);
    78.     }
    79.  
    80.     public void RemoveInstance(InstancedDrawObject instancedDrawObject)
    81.     {
    82.         int foundIndex = -1;
    83.         for (int i = 0; i < usedBoundingSphereCount; ++i)
    84.         {
    85.             if (drawInstances[i] == instancedDrawObject)
    86.             {
    87.                 foundIndex = i;
    88.                 break;
    89.             }
    90.         }
    91.  
    92.         if (foundIndex == -1)
    93.         {
    94.             return;
    95.         }
    96.  
    97.         for (int i = foundIndex; i < usedBoundingSphereCount - 1; ++i)
    98.         {
    99.             drawInstances[i] = drawInstances[i + 1];
    100.             boundingSphere[i] = boundingSphere[i + 1];
    101.         }
    102.  
    103.         for (int i = usedBoundingSphereCount; i < drawInstances.Length; ++i)
    104.         {
    105.             //drawInstances[i] = null;
    106.             //boundingSphere[i] = new BoundingSphere();
    107.         }
    108.  
    109.  
    110.         //Array.Copy(drawInstances, foundIndex + 1, drawInstances, foundIndex, usedBoundingSphereCount - foundIndex - 1);
    111.  
    112.         --usedBoundingSphereCount;
    113.         cullingGroup.SetBoundingSphereCount(usedBoundingSphereCount);
    114.         DestroyImmediate(instancedDrawObject.gameObject);
    115.  
    116.     }
    117.  
    118.     private void Update()
    119.     {
    120.         int x = (int)(pos.x);
    121.         if (x < items.Length)
    122.         {
    123.             InstancedDrawObject drawObject = items[x];
    124.             if (drawObject != null)
    125.             {
    126.                 RemoveInstance(drawObject);
    127.                 items[x] = null;
    128.             }
    129.         }
    130.  
    131.         pos += increment * Time.deltaTime;
    132.         _camera.transform.position += increment * Time.deltaTime;
    133.     }
    134.  
    135.     private void OnDestroy()
    136.     {
    137.         cullingGroup.Dispose();
    138.         cullingGroup = null;
    139.     }
    140. }
    141.  
     

    Attached Files:

    Last edited: Dec 28, 2018
  2. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    3,296
    Have you tried setting bounding sphere reference array again in RemoveInstance?
    E.g.
    Code (CSharp):
    1. --usedBoundingSphereCount;
    2. cullingGroup.SetBoundingSpheres(boundingSphere);
    3. cullingGroup.SetBoundingSphereCount(usedBoundingSphereCount);
    4.      
    5. DestroyImmediate(instancedDrawObject.gameObject);
    I had simillar issues with culling group not updating array data properly when only setting the count. Might be worth trying.

    Alternatively, make sure you're adding / removing correct instances of the objects.
     
  3. Alex1337rus

    Alex1337rus

    Joined:
    Mar 30, 2016
    Posts:
    37
    I have tried but the result is the same.

    I found this method CullingGroup.EraseSwapBack and it probably works.

    Code (CSharp):
    1. public void RemoveInstance(InstancedDrawObject instancedDrawObject)
    2.     {
    3.         int foundIndex = -1;
    4.         for (int i = 0; i < usedBoundingSphereCount; ++i)
    5.         {
    6.             if (drawInstances[i] == instancedDrawObject)
    7.             {
    8.                 foundIndex = i;
    9.                 break;
    10.             }
    11.         }
    12.  
    13.         if (foundIndex == -1)
    14.         {
    15.             return;
    16.         }
    17.  
    18.         drawInstances[foundIndex] = drawInstances[usedBoundingSphereCount - 1];
    19.         cullingGroup.EraseSwapBack(foundIndex);
    20.  
    21.         --usedBoundingSphereCount;
    22.         cullingGroup.SetBoundingSphereCount(usedBoundingSphereCount);
    23.         DestroyImmediate(instancedDrawObject.gameObject);
    24.     }
     
    xVergilx likes this.