Godot will not draw 2D objects out of view.
So, do not worry about GPU resources.
You can confirm this yourself. With the game running, go to the Debugger panel (you can find it on the bottom of Godot editor), and then the Monitor tab. On the left you will see a list of categories. You are looking for 2D. You should see both Items and Draw Calls reflect the objects that are in view. If there is nothing in view, they will fall to zero.
While we are at it, you might also be interested in the profiler. On the same Debugger panel, you will find a Profiler tab. If you enable it, it will show how much time different parts of the game take. Including time dedicated audio, physics, and to execute script functions.
If you are having performance problems, check the Profiler. You know what they say about premature optimization.
As you may have guessed, enemies outside of view still have a cost: Their scripts are still executing (and if they are moving their physics is being computed).
You might or might not want to have them executing. For sake of argument, let us say there are some enemies you want to stop when they are away form the player character.
You can enable or disable callbacks:
These functions take a
bool parameter. Pass
true to enable the callbacks (for example when the player character is nearby), and
false to disable them (when the player character is away).
And how to know if they are near the player character? Put a large detector
Area2D around the player character. Then you can use the
"body_entered" signal to enable them and the
"body_exited" signal to disable them.
As alternative to a large detector
Area2D, you can use
Yes, that means they still have their scripts and their
_ready will run. And they can also respond to signals. So, some animations, timers and similar might still be ticking.
Again, for the sake of argument, let us say you don't want that. What you need is to only load enemies near the player character. That can be with
load or with Background loading.
If we don't have loaded the instances, that also imply there is nothing for our detector
Area2D to detect per-se. So we need to modify our approach.
You might be interested in
InstancePlaceholder. You can create them by adding scene instance to the Scene panel, and the select "Load As Placeholder" from their context menu. However
InstancePlaceholder don't have a transform, so checking distance is not directly an option.
Let us see… We need something with a position. And ideally something for our detector
Area2D to detect. We can use another
Area2D as placeholder!
To the placeholder
Area2D attach an script with a
func that instances whatever necessary (e.g. perhaps it has
InstancePlaceholders as children, and the
replace_by_instance on them) and you want to either have it remove itself (in which case you want to move the children to siblings first) or disable itself (by setting
monitorable to false). Then when we get the
"area_entered" signal call the that
As you can imagine these placeholder
Area2D do not have to represent a single enemy. They can be responsible of triggering the load of multiple enemies. For example, a room full of enemies, that would otherwise be wasting resources being there out of view.
By the way, take advantage of collision layers and masks on both detector
Area2D and placeholder
Area2D so you can filter out any other areas you are not interested in. And, by the way, yes, you can do this with