1
\$\begingroup\$

A creator named NovemberDev made this game without having performance in mind, yet his enemy AI, while being relatively simple, is still extremely fast: his game can have hundreds of enemies all moving and colliding around without too much performance issues.

The only sources of lag in his game are literally the enemy sounds; if you delete all the sound nodes and make the game mute, it runs incredibly smoothly with a large amount of enemies.

like here's the enemy.gd: https://github.com/NovemberDev/novemberdev_soulslike_darksouls_godot/blob/main/Scripts/Enemy.gd

I'd like to replicate his methods, only one problem....he doesn't use areas to detect the player the player position, he uses the tree node.

Autoloads : get_node("/root").add_child(player)

Enemy.gd : distance_to_player = Globals.current_player.global_transform.origin.distance_to(global_transform.origin)

I tried using the same player detection, it was actually my very first method of doing it.

The problem is that the Godot documentation suggests that to save and load the game, one must delete all saved nodes before loading as to avoid the nodes being duplicated every time you save and load.

Straight from Godot docs:

var save_nodes = get_tree().get_nodes_in_group("Persist")
for i in save_nodes:
    i.queue_free()

so whenever you save and load the game, since the enemies are keeping track of a specific node, the game will crash because the node that the enemies where keeping track was deleted and replaced... it doesn't matter that it is literally the same node, a complete clone... godot doesn't recognize it and the game crashes.

So for now, I tried using multiple area nodes, each one with a collision attached to it. That was a bad idea. I also tried to maybe not use area nodes but just create an area in code and use it to define distance... and that wasn't such a big improvement, not at all actually. Rays just make the enemy agent feel like it is blind, and to mimic the effects of areas you have to add dozens on dozens of rays in all directions, otherwise the player can easily hide behind a blade of grass and become invisible to the enemy.

So what other ways are there to detect players/prey/physical things that AI is supposed to detect?

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Take the linked Godot documentation - which is a tutorial - more as an example than a ruling of what you should do. \$\endgroup\$
    – Theraot
    Commented Jul 8, 2023 at 20:56

1 Answer 1

2
\$\begingroup\$

so whenever you save and load the game, since the enemies are keeping track of a specific node, the game will crash because the node that the enemies where keeping track was deleted and replaced... it doesn't matter that it is literally the same node, a complete clone... godot doesn't recognize it and the game crashes.

You can check with is_instance_valid:

var current_player := Globals.current_player
if is_instance_valid(current_player):
    distance_to_player = current_player.global_transform.origin.distance_to(global_transform.origin)
    # ...

You would, of course, update Globals.current_player to the new Node when it becomes available. You might also consider using a signal to notify about it.

See also is_inside_tree, is_queued_for_deletion and NOTIFICATION_PREDELETE.


So for now I tried using multiple area nodes, each one with a collision attached to it and that was a bad idea

You would be checking distance all the time. Which might be OK for a single or for few targets.

On the other hand, using areas gives you the flexibility to define a shape (e.g. have the enemies be able to detect the player further away if they are on the direction they are looking to). And would be easier to handle for certain types of games (e.g. stealth).


also tried to maybe not use area nodes but just create an area in code and use it to define distance...

Look into using intersect_shape instead.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .