Reducing the number of enabled objects by disabling objects whenever possible

Optimization principal 3: Minimize the number of enabled objects in a scene. Sometimes we may not want to completely remove an object, but we can identify times when a scripted component of an object can be safely disabled. If a Monobehaviour script is disabled, then Unity no longer needs to send the object Update() and OnGUI() messages for each frame.

For example, if a non-player character (NPC) should only demonstrate some behavior when the player can see that character, then we only need to be executing the behavior logic when the NPC is visible—the rest of the time we can safely disable the scripted component.

Unity provides the very useful events OnBecameInvisible() and OnBecameVisible(), which informs an object when it moves out of and into the visible area for one or more cameras in the scene.

This recipe illustrates the following rule of thumb: if an object has no reason to be doing actions when it cannot be seen, then we should disable that object while it cannot be seen.

How to do it...

To disable objects to reduce computer processing "workload" requirements, perform the following steps:

  1. Create a new Unity project by importing the Character Controller package.
  2. Create a new terrain.
  3. Add a 3rd Person Controller in the center of the terrain.
  4. Create a new cube just in front of your 3rd Person Controller.
  5. Add the following C# script class to your cube:
    // file: DisableWhenInvisible
    using UnityEngine;
    using System.Collections;
    
    public class DisableWhenInvisible : MonoBehaviour {
      public Transform player;
    
        void OnBecameVisible() {
            enabled = true;
        print ("cube became visible again");
      }
    
        void OnBecameInvisible() {
            enabled = false;
        print ("cube became in-visible");
      }
      
      private void OnGUI() {
        float d = Vector3.Distance( transform.position, player.position);
        GUILayout.Label ("distance from player to cube = " + d);
      }
    }
  6. With the cube selected in the Hierarchy panel, drag your 3rd Person Controller into the Inspector for the public variable player.

How it works...

When visible, the scripted DisableWhenInvisible component of the cube recalculates and displays the distance from itself to the transform of the 3rd Person Controller, via the player variable in the OnGUI() method for each frame. However, when this object receives the OnBecameInvisible() message, the object sets its enabled property to false. This results in Unity no longer sending Update() and OnGUI() messages to the object, so the distance calculation in OnGUI() is no longer performed, thus reducing the game's processing workload. Upon receiving the OnBecameVisible() message, the enabled property is set back to true, and the object will then receive Update() and OnGUI() messages for each frame. Note that you can see the scripted component become disabled by seeing the blue "tick" in its Inspector checkbox disappear, if you have the cube selected in the Hierarchy panel, when running the game.

There's more...

The following are some details you don't want to miss:

Another common case – only enable after OnTrigger()

Another common situation is that we only want a scripted component to be active if the player's character is nearby (within some minimum distance). In these situations, a sphere collider can be set up, and the scripted component can be enabled only when the player's character enters that sphere. This can be implemented using the OnTriggerEnter() and OnTriggerExit() events; for example:

private void OnTriggerEnter(Collider hitObjectCollider) {
if (hitObjectCollider.CompareTag("Player"))
enabled = true;
}

private void OnTriggerExit(Collider hitObjectCollider) {
if (hitObjectCollider.CompareTag("Player"))
enabled = false;
}

Going one step further – make the parent GameObject inactive

In some cases you can go one step further, and make the parent GameObject that contains the scripted component "inactive". This is just like deselecting the checkbox next to the GameObject in the Inspector.

Going one step further – make the parent GameObject inactive

To deactivate the parent GameObject, you set its active property to false:

void OnBecameInvisible() {
  gameObject.SetActive(false);
  print ("cube became in-visible");
}

Note, however, that an inactive GameObject does not receive any messages, so it will not receive the OnBecameVisible() message; and this may not be appropriate for every object that is out of sight of the camera. However, when deactivating objects is appropriate, a larger performance saving is made over simply disabling a single scripted Monobehaviour component of a GameObject.

The only way to reactivate an inactive object is for another object to set the GameObject's active property back to true. The following script, when added to an active GameObject (such as terrain or controller), will display a button to demonstrate how an inactive object can be reactivated. For this script to work, the public cubeGO variable must be set by dragging the cube over the variable in the Inspector:

// file: MakeCubeActive.cs
using UnityEngine;
using System.Collections;

public class MakeCubeActive : MonoBehaviour {
  public GameObject cubeGO;

  private void OnGUI(){
    bool makeCubeActiveButtonClicked = GUILayout.Button("make cube active");
    if( makeCubeActiveButtonClicked )
      cubeGO.SetActive(true);
  }
}

See also

  • The Reducing the number of objects by destroying objects at a "death" time recipe
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.83.96