Question about Group: does it iterate over the whole tree?

Godot Version

4.4

Question

I am looking at Groups — Godot Engine (stable) documentation in English and from the very beginning of the document: Groups in Godot work like tags in other software.

From this function here:

var guards = get_tree().get_nodes_in_group("guards")

Does this mean it iterates through the whole tree in order to get the Nodes within the group “guards”? So if I have only 10 Nodes that are “guards” and suppose I have 100 Nodes versus 10,000 Nodes, this get_nodes_in_group will be slower when I have 10,000 Nodes in the tree, yes? Does it work that way?

If performance is a concern, then in this case, I am thinking of creating my own Array of Guards object and add my 10 guards in there so when I want to refer to the guards, I just call the Array instead to always iterate through only 10 objects.

But still, is my understanding on the paragraph above regarding 100 Nodes versus 10,000 Nodes and the group implementation correct?

Help > Programming

No, it doesn’t work that way.

However if you had 1,000 guards and the group is globally scoped, you are going to search through all 1,000 guards when you only needed the 10 in the room.

This is a good idea. Another way of doing it is to create a Node2D or Node3D in your level, name it guards, and put all the guards in the level under that node so you can easily find them with guards.get_children(). Then you don’t have to have a separate variable to track them.

The only thing I personally use groups for is for saving games. I tag everything I want saved in a group and make sure it has a save() and load() function. Whenever I save or load a game, each object takes care of its own state.

2 Likes

@dragonforge-dev

No, it doesn’t work that way.

However if you had 1,000 guards and the group is globally scoped, you are going to search through all 1,000 guards when you only needed the 10 in the room.

I am not sure if I get this.

So globally scoped work the way I am thinking, but for the locally scoped doesn’t work the way I think?

If it doesn’t iterate through the tree, then how does it pick the nodes that are assigned to the selected group?

Groups are saved in a HashMap internally godot/scene/main/scene_tree.h at 71a9948157dc2d5cc71fcb456c9d96656678757d · godotengine/godot · GitHub so it won’t parse the whole tree looking for them.

2 Likes

@mrcdk thank you for that. This means using Group will be faster than implementing my own Array and Dictionary in gdscript by a tiny margin, right?

Because majority of logic will be in gdscript. Ex. What will each guard do, etc., using Group hashmap in this case will be a more preferable choice even though the performance gain should be quite tiny, yes?

Pretty much, yes. I doubt you’ll find any substantial performance difference between using a group or an array.

1 Like

To be clear, every item in the group gets iterated over when you call get_node_in_group(). Only the node’s groups itself are iterated over if you call is_in_group()

@mrcdk answered the question for you.

A primitive is a primitive. I doubt you’ll see any performance difference either way.

I’m not sure what exactly you’re planning to do here, and perhaps it’s just a difference in approaches. But having a controller tell an enemy what to do every frame is going to result in decentralized code. This is what I was trying to get at earlier.

  1. If you want to know if a guard is a guard, you can define a class_name of Guard and then check if node is Guard: in your code. So is_in_group() becomes superfluous.
  2. You must remember to add any instance of an object to the group both in the editor or in code. If you forget, your code will fail without an error and you will have to remember to check if an object is in the group.
  3. You must be aware of the scope of your groups. Because even if you only have an 11th guard sitting in another room, it’s going to get commands even if it’s not on screen. If one of those commands is queue_free() you’ll have objects disappearing when you don’t want them to - and again no error handling to tell you why. Or smaller bugs like every time you walk in the room, the guard is in the wrong place.
  4. You are not guaranteed to get the guards in any particular order. Which means you can’t have guard one do one thing, and guards 2-10 something else. They all must behave identically or only be given randomized commands.

I’d recommend that you make every guard autonomous, and tell it what it should be doing. If you need to tweak a single guard’s behavior it’s much easier than tweaking an uber-script. You just click on the guard, tweak an exported variable, or inherit the script and override it.

Like I said, this is more of a difference in approach, but in every question I have seen on these boards about an issue with groups, the answer has been that Godot has a better way to do that than whatever approach was being tried using a group.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.