Enabling & Disabling Child Objects Based on Player Distance in Unity 3D

Sometimes you need to work with a large number of child objects that cover a large area of distance.  When I was working with a large meteor field for my game that had about 500 meteors, I found that I was using more system resources than necessary because all the meteor mesh was constantly there and being calculate.  To get around that, I wrote a script that checks the distance between the player and the object every X seconds.  If the object is within range of the player then enable them.  If not, then disable them.

Why every X seconds?  If it was done every frame I may as well have just kept the objects all visible.  Doing it, say, every 1 second cuts the processing down to about 1/30th.  Every 5 seconds 1/150th etc.

Visible Children Based On Distance - In Unity 3D

The blue circle in the middle represents the Player's location. The larger circle represents the distance that the child objects are visible from. The darker area is where the child objects would be disable and therefore not visible.

The process consists of two scripts for me.  One that sits on the parent and does the checking, since it’s always enabled.  The second script gets assigned to each child and contains two functions – enable and disable.

Here is the source code for the distance checker that should be placed on the parent object.

/* Written by Cassius Adams for the Super Space Trooper video game. http://www.SuperSpaceTrooper.com */
 
/* This script will enable and disable child objects based upon their distance
to the player.  It may be useful where you're trying to save resources if
there is a large number of child objects.  This script should be placed on
the parent object */
 
var player : GameObject; // Get the player so we can check for distance every X seconds (distanceCheck)
var distanceCheck : int = 1.0; // Time between checking distance of player to rock
var visibleDistance : int = 30; // Distance between player and rock before being visible
private var tempTime : float = 0; // Holds the next time to check time
private var objectDistance : float = 0; // Holds the distance to rock
 
var childScriptEnableDisable : ChildEnableDisable; // Gets the ChildEnableDisable script
 
function Start () {
	for (var child : Transform in transform) {
		// Lets us specify which child to run the enable/disable script on.
		childScriptEnableDisable = child.transform.gameObject.AddComponent(ChildEnableDisable);
		childScriptEnableDisable.DoDisable();
	}
}
 
function Update () {
	if(tempTime <= Time.time) {
		// Get the distance to all the child objects
		for (var child : Transform in transform) {
			if (player && child)
			    objectDistance = Vector3.Distance(player.transform.position, child.transform.position);
			if(objectDistance <= visibleDistance && child.transform.gameObject.active == false) {
				/* Then we call the enable/disable script and tell it to enable.
				Alternatively, we could just enable and disable materials, but I
				feel like completely disabling the objects may save resources. */
				childScriptEnableDisable = child.transform.gameObject.GetComponent(ChildEnableDisable);
				childScriptEnableDisable.DoEnable();
				// We should also disable currently enabled objects if they're farther than objectDistance
			} else if (objectDistance > visibleDistance && child.transform.gameObject.active == true) {
				childScriptEnableDisable = child.transform.gameObject.GetComponent(ChildEnableDisable);
				childScriptEnableDisable.DoDisable();
			}
		}
		tempTime = distanceCheck + Time.time;
	}
}

Don’t forget to assign your player’s GameObject to the ‘player’ variable in the above script through the hierarchy.

Here is the source code that will be assigned to the child objects.  You do not need to place this onto the child objects, the above script will do that automatically.

/* Written by Cassius Adams for the Super Space Trooper video game. http://www.SuperSpaceTrooper.com */
 
/*
This script will be assigned to the parent object's meteorScriptEnableDisable
variable in the DistanceVisible script.
 
The purpose for this script is to allow us to keep the child objects in
the hierarchy but choose when each is visible and when it's not.  It
is usually enabled by the container when the player is within range
to activate the enemy.
*/
 
function DoDisable () { // Disables the game object and scripts
	gameObject.active = false;
}
 
function DoEnable () { // Enables the game object and scripts
	gameObject.active = true;
}

This is one approach to doing this.  Alternatively, of course, we could add a bunch of colliders to the child objects and then enable them when the player passes through the collider.  I feel like that would also take up additional resources as collisions are checked for each Update() frame.

If you find this script useful, or have another way of using it, please do comment below. :)

Posted in Javascript JS, Super Space Trooper, Unity 3D, Video Game Development

Leave a Reply

Your email address will not be published. Required fields are marked *

*


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>