Godot Version
4.5
Question
I’m working on implementing some basic AI to enemies in my first person sword fighting game and I’m having a hard time deicing how I want them to get a reference to players or npcs. There are a few options I can think of, but they all come with some downsides:
1) Player Reference Singleton or Export Variable
This is what I most commonly see being done and for a good reason. It’s super easy to just give the enemy reference to the player right away with an auto load PlayerRef script or by dropping the player into an export variable on the EnemyBase class.
However, I feel this method is limiting. I’m very early into development so don’t know where this game is going yet. Even though this would work fine for me now, down the line it’s probable that the enemy ai is going to need to target other NPC’s or potentially even multiple players. For that reason I’d opted for a different approach:
2) Groups
Currently I’m using groups for my enemy to get reference to the Player. On ready the Player adds itself the Players Group. From the Enemy script I have a target_player function that will get_tree().get_nodes_in_group("Player") and for each node in the Players group, I check distance, and then keep a reference to closest player as var target_player: Player.
As my game is now the target player will always just be the same, since right now there is only ever one node in the Player group. However, this feels very scalable. If ever implement multiplayer, my function can already choose it’s target_player when there are multiple players. Additionally, I can easily expand it to reference NPC’s too by just having it search another group like HostileCharacters or something and rename target_player to target_actor.
My issue with this set up is that it feels expensive. I could be wrong, but it seems excessive for the enemy to always know what the closest enemy is, and consistently be checking every node in the tree to find nodes in the Player group. So I’m considering switching it to:
3) Area3D
As you can probably guess, this option is just putting an Area3D in my EnemyBase scene. I can use the body_entered and body_exited signals to make an array of players (or hostile NPCs) that are inside the area. I can then use that Array in a function to set target as one of the bodies.
In my head this option makes the most sense, however I’m worried about the area3Ds causing performance issues if there are a lot of enemies at once. Especially since my EnemyBase scene already has an Area3D serving an unrelated function.
Is there another more efficient way to do this that I’m not thinking of? If not, would swapping my current system for the Area3D option be better or worse for performance?