Best way to keep an updated list of GameObjects

So… I need to process all the GameObjects every frame (possibly only those with a renderer on them). What would be the fastest way to achieve that? I suppose the answer is to directly access some Unity’s internal array that stores them. I could traverse the hierarchy, but that sounds kinda slow. I’ve also read Unity keeps an array of GameObjects per tag, but the only way to get a list of the tags is using an undocumented editor only function.
I could also keep my own array if there was a method to detect when a new GameObject is created.

What do you think?

I have no idea on impact, suppose it depends on the number of objects in you per scene, but, why not, in Update(), run a for() loop which runs thru each object. If it has a renderer, add to list.

Seems simple enough.

That’s the problem! How to loop through them efficiently? Object.FindObjectsOfType is incredibly slow.

Why not transform in Transform.?

I’d have to do that recursively, though… I guess… Won’t that be slow as well?

Sigh… I guess I’m sometimes over obsessed with performance.

Performance is important, but what causes bad performance should be avoided…

Again, why won’t this work…

void Update(){
for(Transform child in transform){
if ( child.gameObject.renderer)
child.AddToList();
}
}

Just place all objects in one transform.

Doesn’t that get me only the immediate children of the current GameObject? I need every GameObject in the hierarchy.

True indeed.

Perhaps, each object, manager, should run thru its children, and report back to the main list.

This is tough, how is your system set up? Are you constantly changing the number of objects in scene I guess?

Well… I’d like to get this working in the general case.

And what you say could work, if I recursively went through the children of every transform, starting with Transform.root. But again, I hope there is a faster way.

Well, the only way I can see beyond setActiveRecursively, would be to have each root object, be a manager onto itself, where by it knows, pre hand how many renderer’s it has. On its awake, or start, it passes this number to the all knowing manager. This all knowing manager, or main manager, holds total renderer’s of all the objects.

So, since you must know each frame (why? But I digress), I would simply have each root manager, pass to the main manager, its count. I this root manager loses or gains or is itself destroyed, it passes this count to the main manager. This also benefits as it loses the essential airy that you need each frame to get how many renderer’s are in scene. Instead, when one is added or lost, this info is passed to the main manager.

Yah dig?

Not really… there’s only one root object in the hierarchy. You probably mean any object that has children? Also, keeping track of only the counts wouldn’t do… I need to iterate over them.
So you’re suggesting that on update, every parent object would build an array of the renderers it has and pass it over to the main manager, which would then add them up? That could work, but my scene can be quite dynamic. I’d have to somehow be able to programatically add this script to every GameObject that becomes a parent, which is another challenge by itself.

Wonder why I need a list of all renderers each frame? Because I want to render them manually.

So, I did some benchmarking of these five methods I could come up with (just returning the count for now):

	int GatherRenderers1() {
		int amnt = 0;
		GameObject[] matches = FindObjectsOfType(typeof(GameObject)) as GameObject[];
		foreach (GameObject go in matches) {
			if (go.renderer) {
				amnt += 1;
			}
		}
		return amnt;
	}
	
	int GatherRenderers2() {
		Renderer[] matches = FindObjectsOfType(typeof(Renderer)) as Renderer[];
		return matches.Length;
	}
	
	int GatherRenderers3() {
		Renderer[] matches = Resources.FindObjectsOfTypeAll(typeof(Renderer)) as Renderer[];
		return matches.Length;
	}
	
	int GatherRenderers4(GameObject rootObject) {
		
		Renderer[] matches = rootObject.GetComponentsInChildren<Renderer>() as Renderer[];
		return matches.Length;
	}
	
	int GatherRenderers5(Transform parent) {
		int amnt = 0;
		if (parent.gameObject.renderer) {
			amnt += 1;
		}
		for (int i = 0; i < parent.childCount; i++) {
			amnt += GatherRenderers5(parent.GetChild(i));
		}
		return amnt;
	}
	
	void Update() {
		Transform root = gameObject.transform.root;
		
		for (int i = 0; i < 100; i++) {
			Profiler.BeginSample("FindObjectsOfType(typeof(GameObject))");
			GatherRenderers1();
			Profiler.EndSample();
			
			Profiler.BeginSample("FindObjectsOfType(typeof(Renderer))");
			GatherRenderers2();
			Profiler.EndSample();
	
			Profiler.BeginSample("Resources.FindObjectsOfTypeAll(typeof(Renderer))");
			GatherRenderers3();
			Profiler.EndSample();
			
			Profiler.BeginSample("root.GetComponentsInChildren<Renderer>()");
			GatherRenderers4(root.gameObject);
			Profiler.EndSample();
			
			Profiler.BeginSample("Traverse hierarchy");
			GatherRenderers5(root);
			Profiler.EndSample();
		}
	}

FindGameObjectsWithTag unfortunately doesn’t work for untagged objects… That’s a bummer… I was expecting it to be the fastest. Anyways, here are the results:

root.GetComponentsInChildren seems to be the fastest so far… but requires maintaining a root GameObject.
Still… I’m 100% sure Unity does have an internal list of all Renderers somewhere. It’s just a matter of finding it. Any clues?

Have you considered using a custom type wrapper and an object pool for that type? Your custom type could implement methods that added itself to the pool when it is instantiated (based on some criteria), the pool could fire events or whatnot when/if it is updated. Since the logic to get the objects you want will already be in place, per frame you would just iterate over the pool.

Why would you search for the objects every frame? You only need to search once, at the start, and then every time one of your scripts add/destroys an object of that type it adds/removes it from that list?

I thought of that, but I’m planning to use this in an asset that should work for any kind of a scene. What you’re suggesting would require the user to add a script to every existing object and modify all current scripts (some of which might belong to other assets) to also mark any gameobject it might create. As you can see, it’s the least practical way possible. It would be so easy to miss an object.

If only I could overwrite the Renderer class or have some way of knowing when a new instance of a Renderer has appeared…