Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Find All Child Meshes

Discussion in 'Scripting' started by Marble, Sep 27, 2006.

  1. Marble

    Marble

    Joined:
    Aug 29, 2005
    Posts:
    1,269
    I have a building that has four "floor" gameObjects as children. I want to be able to disable rendering for each floor when the player leaves it for the next one, like a portal culler.

    This would be easy if each floor was a single mesh, but each one has a variety of children, some of which have children, that include beds, tables, etc. I can't just disable the whole floor gameObject because there might be character objects that are still colliding with the floor mesh, or using its scripts, etc. How do I access all the mesh renderers in a hierarchy so I can disable and reenable them?
     
  2. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    What I did in a similar situation was just to assign a tag to a set of objects you want to be able to disable/enable. So if you have four floors, make four tags, called something like Floor1, Floor2, etc. Then assign all objects on each floor the appropriate tag. Then do something like:

    Code (csharp):
    1.  
    2. function TurnStuffOn(objectSet : String) {
    3.     var activateObjects = GameObject.FindGameObjectsWithTag (objectSet);
    4.     for (var thisObject in activateObjects) {
    5.         thisObject.renderer.enabled = true;
    6.     }
    7. }
    8.  
    9. function TurnStuffOff(objectSet : String) {
    10.     var deactivateObjects = GameObject.FindGameObjectsWithTag (objectSet);
    11.     for (var thisObject in deactivateObjects) {
    12.         thisObject.renderer.enabled = false;
    13.     }
    14. }
    15.  
    So to turn Floor2 rendering off, you'd just do

    Code (csharp):
    1.  
    2. TurnStuffOff("Floor2");
    3.  
    And to turn rendering on...well, that's pretty obvious. ;)

    --Eric
     
  3. Marble

    Marble

    Joined:
    Aug 29, 2005
    Posts:
    1,269
    Yeah, that sounds good, as perhaps would creating a layer for each floor and just changing the culling on the camera. The only catch is that if there are several buildings, side by side for example, their floors will also be culled, unless there's a separate tag for each floor of each building, which could get tedious.

    I keep thinking it might be easier to search through a gameObject hierarchy for the mesh renderers, but I don't know how.
     
  4. freyr

    freyr

    Joined:
    Apr 7, 2005
    Posts:
    1,148
    Well you could just recurse through the thransform hierarchy -- although I'm think that using layers and enabling and disabling them in the camera is more efficient. (If you have more than one building, you could use a method similar to the one below to turn off all floors in a building you're exiting.)

    Code (csharp):
    1.  
    2. function EnableRenderersRecursive(root : Transform, enable : bool) {
    3.    if( root.renderer )
    4.       root.renderer.enabled = enable;
    5.  
    6.    for(var child : Transform in root) {
    7.       EnableRenderersRecursive(child, enable);
    8.    }
    9. }
    10.  
    This requires you to group all objects on the same floor under a single parent object (Which can be an empty game object. -- the function above makes sure there is a renderer attached to the object before attempting to set renderer.enabled.)

    You then use it in code like this:
    Code (csharp):
    1.  
    2. var floor1 : Transform;
    3. var floor2 : Transform;
    4.  
    5. // Disable floor1:
    6. EnableRenderersRecursive(floor1, false);
    7. // Enable floor2:
    8. EnableRenderersRecursive(floor2, true);
    9.  
     
  5. freyr

    freyr

    Joined:
    Apr 7, 2005
    Posts:
    1,148
    ... or you could use messages to handle finding all the children:

    Code (csharp):
    1.  
    2. // AutoEnabler.js -- attach this to all objects
    3. // that have a renderer.
    4. function EnableMsg( enable : bool ) {
    5.    renderer.enabled=enable;
    6. }
    7.  
    Code (csharp):
    1.  
    2. // Floor.js -- attach this script to
    3. // the root object of each floor
    4. function Enable(enable : bool) {
    5.    BroadcastMessage("EnableMsg", enable,
    6.       SendMessageOptions.DontRequireReceiver);
    7. }
    8.  
    Then the code for enabling and disabling floors would look like this:
    Code (csharp):
    1.  
    2. var floor1 : Floor;
    3. var floor2 : Floor;
    4.  
    5. // Enable floor1:
    6. floor1.Enable(true);
    7. // Disable floor2:
    8. floor2.Enable(false);
    9.  
     
  6. Marble

    Marble

    Joined:
    Aug 29, 2005
    Posts:
    1,269
    Great! I'll try this out tonight. It's this fundamental stuff that gets me—because it's so simple. Specifically, "if( root.renderer )" is just so elegant that it probably never would have occurred to me.