Search Unity

visibility / occlusion triggers

Discussion in 'Scripting' started by warby, May 21, 2009.

  1. warby

    warby

    Joined:
    Mar 23, 2009
    Posts:
    162
    i have the following scenario

    i have 1 big gamobject/folder with 400 objects inside lets call it ROOM_A a door with a small S-shaped corridor and another bit gameobject/folder with roughly 500 more objects inside lets call it ROOM_B

    ROOM_A and ROOM_B can never be seen at the same time so i want to turn them off while you are in the other room ! for framerate optimization


    i was trying to write myself a simple script i could attach to a trigger box where i could choose a gameobject/folder and as long as you are standing inside that box the gameobject/folder and all its children are visible as soon as i leave that trigger it will become invisible:

    here is what i tried
    Code (csharp):
    1.  
    2.  
    3. var cull_this : UnityEngine.GameObject;
    4.  
    5.  
    6. function OnTriggerEnter (col : Collider)
    7. {
    8. cull_this.SetActiveRecursively(true);
    9. }
    10.  
    11.  
    12. function OnTriggerExit (col : Collider)
    13. {
    14. cull_this.SetActiveRecursively(false);
    15. }
    16.  
    this works ! but comes with a roughly 3-6 seconds of lag when the room is being activated ... totally unacceptable

    so i tried to just toggle the renderer checkbox on all the children instead:



    Code (csharp):
    1. var cull_this : UnityEngine.GameObject;
    2.  
    3.  
    4. function OnTriggerEnter (col : Collider)
    5. {
    6. GameObject.GetComponentsInChildren.renderer.enabled = false;
    7. }
    8.  
    9.  
    10. function OnTriggerExit (col : Collider)
    11. {
    12. GameObject.GetComponentsInChildren.renderer.enabled = true;
    13. }
    but all this does is give me this error message:

    Assets/Scripts/Misc/culling_system.js(7,13): BCE0020: An instance of type 'UnityEngine.GameObject' is required to access non static member 'GetComponentsInChildren'.

    i don't understand this error message i thought i was using UnityEngine.GameObject ... what am i doing wrong ?!
     
  2. Dreamora

    Dreamora

    Joined:
    Apr 5, 2008
    Posts:
    26,601
    GetComponentsInChildren is a function and it returns an array of objects
    The script reference on that commands might be helpfull to learn how to work with arrays

    Generally, the problem you have found in the first attempt is that you inject a mass of new game objects into the simulation in one go. Thats pretty heavy if dozens of collisions and renderers are just switched on from one moment to the next
     
  3. warby

    warby

    Joined:
    Mar 23, 2009
    Posts:
    162
    i dont want hem to stop colliding or stop simulating while off i just don't want them to draw. all other game engines can do this without lag so i am sure unity can do aswell easily i just don't know with what command ^^
     
  4. Randy-Edmonds

    Randy-Edmonds

    Joined:
    Oct 10, 2005
    Posts:
    1,122
    Why not simply enable/disable the renderer components, as opposed to the entire gameobject? This should be fast. If it still causes a lag, you might try batching it in a coroutine... doing a dozen (or so) at a time over the course of a couple seconds.
     
  5. Randy-Edmonds

    Randy-Edmonds

    Joined:
    Oct 10, 2005
    Posts:
    1,122
    Another idea would be to set the camera's far clipping level such that when in one room the other room is not rendered (this only works if the rooms are far enough away from each other).

    Or... another idea would be to use two cameras. Have each set to render a certain set of layers that corresponds to particular room. Then simply toggle the cameras based on what room the player is inside.
     
  6. warby

    warby

    Joined:
    Mar 23, 2009
    Posts:
    162
    thats what i tried with the second script but unity wouldnt let me but i dont understand the error message

    how can i recursively deactivate all renderers under a root node ?!
     
  7. Randy-Edmonds

    Randy-Edmonds

    Joined:
    Oct 10, 2005
    Posts:
    1,122
    This code will disable all the renderers....

    Code (csharp):
    1.  
    2. var AllRenderers = GetComponentsInChildren(Renderer);
    3.  
    4. for (var thisRenderer: Renderer in AllRenderers ) {
    5.    thisRenderer.enabled = false;
    6. }
    7.  
     
  8. warby

    warby

    Joined:
    Mar 23, 2009
    Posts:
    162
    you are DA MAN !


    this works like a charm ! so the full script that works now is:


    Code (csharp):
    1. var cull_this: UnityEngine.GameObject;
    2.  
    3.  
    4.  
    5. function Start ()
    6. {
    7. var AllRenderers = cull_this.GetComponentsInChildren(Renderer);
    8.  
    9. for (var thisRenderer: Renderer in AllRenderers ) {
    10.    thisRenderer.enabled = false;
    11. }
    12. }
    13.  
    14.  
    15. function OnTriggerEnter (col : Collider)
    16. {
    17. var AllRenderers = cull_this.GetComponentsInChildren(Renderer);
    18.  
    19. for (var thisRenderer: Renderer in AllRenderers ) {
    20.    thisRenderer.enabled = true;
    21. }
    22. }
    23.  
    24.  
    25. function OnTriggerExit (col : Collider)
    26. {
    27. var AllRenderers = cull_this.GetComponentsInChildren(Renderer);
    28.  
    29. for (var thisRenderer: Renderer in AllRenderers ) {
    30.    thisRenderer.enabled = false;
    31. }
    32. }
    33.  
    34.  
    35.  
    36.  
    37.  
    38.  

    in case some other code noob artist like me shows up and wants to optimize his scene :)))

    HOW TO USE:
    - put all objects in one room into a group/folder/gameobject
    - make a triggerbox that encompasses all the area from where the room can be seen (probably the dimensions of the room itself and the most nearby corridors)
    - assign this script to the trigger box
    - in the exposed cull_this variable field choose the room

    DONE

    this manual-occlusion script is now public property of the unity community
     
  9. DocSWAB

    DocSWAB

    Joined:
    Aug 28, 2006
    Posts:
    615
    Keep in mind that calling GetComponent or FindObject, etc. has a considerable amount of overhead.

    If the objects in question are all present at startup, then your Start function should assign the results of the GetComponent call to an array variable and then you can enable/disable renderers etc. by iterating on that array instead of doing the GetComponent call each time you want to switch things on and off.