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?
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:
function TurnStuffOn(objectSet : String) {
var activateObjects = GameObject.FindGameObjectsWithTag (objectSet);
for (var thisObject in activateObjects) {
thisObject.renderer.enabled = true;
}
}
function TurnStuffOff(objectSet : String) {
var deactivateObjects = GameObject.FindGameObjectsWithTag (objectSet);
for (var thisObject in deactivateObjects) {
thisObject.renderer.enabled = false;
}
}
So to turn Floor2 rendering off, you’d just do
TurnStuffOff("Floor2");
And to turn rendering on…well, that’s pretty obvious.
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.
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.)
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:
var floor1 : Transform;
var floor2 : Transform;
// Disable floor1:
EnableRenderersRecursive(floor1, false);
// Enable floor2:
EnableRenderersRecursive(floor2, true);
… or you could use messages to handle finding all the children:
// AutoEnabler.js -- attach this to all objects
// that have a renderer.
function EnableMsg( enable : bool ) {
renderer.enabled=enable;
}
// Floor.js -- attach this script to
// the root object of each floor
function Enable(enable : bool) {
BroadcastMessage("EnableMsg", enable,
SendMessageOptions.DontRequireReceiver);
}
Then the code for enabling and disabling floors would look like this:
var floor1 : Floor;
var floor2 : Floor;
// Enable floor1:
floor1.Enable(true);
// Disable floor2:
floor2.Enable(false);
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.