Deactivating off-camera objects and vice-versa

I’ve been reading about this and the OnBecameVisible() and OnBecameInvisible() functions. If I were to just layout/build my entire level as a Scene in Unity (2D) with all objects/enemies/power-ups, etc. won’t they just be running all the time?

So before I took to the forums, I built a prototype. I built a level/scene and put two ‘enemy’ objects on far sides of the level. The Player spawns in the center. Sure enough, the enemy objects are having their Update() method called every frame even when they are nowhere near being on camera.

So, this proves my hypothesis that there is no automagic ‘culling’. A little searching shined me on the the two aforementioned functions which seem awesome.

My question is, how are people implementing these so that I can layout my entire level/scene with scenery, enemies, power-ups, etc. and only have an object be drawn and have Update() and FixedUpdate(), etc., called when they are on camera?

There is culling, in the sense that the sprites/textures aren’t rendered, which is generally a bigger operation than most scripts you have on them. If you open the Stats window, you can see the draw-calls drop when they go off screen.

I guess you could have a secondary script on the objects which use OnBecameVisible() and OnBecameInvisible() to disable or enable the main script of the object, without having to deal with the issue of trying to enable disabled objects.

Ok. So some more experimenting allowed me to prove it was possible. I’m still interested if there is a proven pattern for this. But here is my POC.

I created a Quad and called it EnemyCube. I gave it this script. The two OnBecame(In)Visible functions require a Renderer to be present. Now, when my enemy cube’s are off camera, I see no debug log messages. As soon as one comes on camera, I see the messages. Update() and FixedUpdate() are still running, but return very quickly after checking a boolean var’s state.

using UnityEngine;
using System.Collections;

public class EnemyCubeScript : MonoBehaviour {
	public bool isActive = false;


	// Use this for initialization
	void Start () {
	
	}

	// When the Camera no sees us
	void OnBecameInvisible() {
		isActive = false;
		Debug.Log ("EnemyCube deactivating");
	}
	
	// When the Camera sees us
	void OnBecameVisible() {
		isActive = true;
		Debug.Log ("EnemyCube activating");
	}

	void FixedUpdate () {
		if (!isActive)
			return;
		Debug.Log ("EnemyCube active!");
	}

	// Update is called once per frame
	void Update () {
		if (!isActive)
			return;
		Debug.Log ("EnemyCube active!");
	}
}

Is there a better way to do this?

Thank you. That is good to know. I’ll feel better knowing I’ve minimized the (Fixed)Update() side of things also. See my reply-post.