Search Unity

LOD culled gameobject still interacts with raycast

Discussion in 'Scripting' started by the_mr_matt, Dec 5, 2018.

  1. the_mr_matt

    the_mr_matt

    Joined:
    Jul 21, 2015
    Posts:
    124
    The camera is sort of top down and the player can move objects around, rotate them, delete them etc. I use a raycast to check what was hit when the player clicks. But some objects are culled by the LOD group when far away, but the LOD group only disables the renderer, not the colliders, so it still interacts with the raycast. This means a player can move or delete an object that they can't even see.

    I've tried looping through all the renderers in the lod group and using renderer.isVisible but it doesn't solve the problem of collision and raycasts. I'd really rather not poll isCulled every frame in update either because there are thousands of gameobjects, that would be horrible for performance.

    Code (CSharp):
    1. LODGroup lodGroup = GetComponent<LODGroup>();
    2. LOD[] LODs = lodGroup.GetLODs();
    3. for (int i = 0; i < LODs.Length; i++)
    4. {
    5.      LODRenderers = LODs[i].renderers;
    6. }
    7.  
    8. bool isCulled = true;
    9.  
    10. for (int i = 0; i < LODRenderers.Length; i++)
    11. {
    12.     if (LODRenderers[i].isVisible)
    13.     {
    14.         isCulled = false;
    15.     }
    16. }
     
  2. What do you want to happen? Because you forgot to mention that. If you don't want anything to happen when the player click on a culled object than just check for the isVisible on the renderer of that one object's and if it's false, you just drop that click.
     
  3. ZombieTFK

    ZombieTFK

    Joined:
    Sep 6, 2016
    Posts:
    55
    If you only want your raycasts to work from a certain distance away, have you considered setting the maxDistance parameter in your raycast?
     
    SparrowGS and Lurking-Ninja like this.
  4. the_mr_matt

    the_mr_matt

    Joined:
    Jul 21, 2015
    Posts:
    124
    Good point. When the player clicks on a culled object, I want the raycast to go right through it so that it can get the object behind it. At this time, only trees are being culled. I have road pieces and buildings that are not being culled. Therefore, if a tree is in front of a road and is culled, it stops the raycast even though the player cannot see it. Instead, the raycast should go through the tree and hit the road, as though the tree were set inactive in the hierarchy.

    I don't know what value I would use. The LOD distances are really tricky. They are a percentage, not a value, they appear to be non linear, and they are inconsistent between objects. If I set the same percentage value on all the assets, some of them are still visible from further away than others.
     
  5. the_mr_matt

    the_mr_matt

    Joined:
    Jul 21, 2015
    Posts:
    124
    What's an efficient way to sort them? I don't really want to use linq.
     
  6. the_mr_matt

    the_mr_matt

    Joined:
    Jul 21, 2015
    Posts:
    124
    Nevermind, didn't need linq.

    Code (CSharp):
    1. float minDist = Mathf.Infinity;
    2. int minDistIndex = -1;
    3.  
    4. for (int i = 0; i < m_RaycastHits.Length; i++)
    5. {
    6.     if (m_RaycastHits[i].collider == null)
    7.         continue;
    8.  
    9.     if (m_RaycastHits[i].distance < minDist)
    10.     {
    11.         Element element = m_RaycastHits[i].collider.GetComponent<Element>();
    12.    
    13.          if (element.IsCulled)
    14.              continue;
    15.  
    16.          minDist = m_RaycastHits[i].distance;
    17.          minDistIndex = i;
    18.     }
    19. }
    20.  
    21. if(minDistIndex != -1)
    22. {
    23.     //do something with m_RaycastHits[minDistIndex]
    24. }
    25.  
     
  7. ZombieTFK

    ZombieTFK

    Joined:
    Sep 6, 2016
    Posts:
    55
    Not to derail but why RaycastNonAlloc instead of RaycastAll? Is the overhead of the gc really that bad?

    You can use the
    Array.Sort
    static System utility method, and pass in a delegate sorting method (comparing the distances). I've also not tested it, but I'd also assume they would already be in order anyway?
     
    Last edited: Dec 5, 2018
  8. the_mr_matt

    the_mr_matt

    Joined:
    Jul 21, 2015
    Posts:
    124
    I think I found out why renderer.isVisible was so inconsistent for me earlier. It seems that it is affected by not only the game view, but also the scene view. So if my camera was really far away in game and it was culled in game, but the camera in scene was close, it would still return true. Upon closing the scene view, everything seems to be working as expected.
     
    Lurking-Ninja likes this.
  9. qkson

    qkson

    Joined:
    Jan 15, 2018
    Posts:
    77
    Yes, the isVisible works also when the gameobject is visible in scene view which can be a bit disorienting, you have to take that into account when testing the game.
     
  10. Nope.
    And yes, Array.Sort the best way to go I believe.

    Because it's a small price to pay (fix array size) for no garbage. Their behavior otherwise the same.
     
    ZombieTFK likes this.
  11. SparrowGS

    SparrowGS

    Joined:
    Apr 6, 2017
    Posts:
    2,536
    Just to point out, IsVisible returns true even if you can only see 1 pixel of the shadow of the object.