0 votes

In a project I've been working on I have been trying to set up an 'aggro radius' for another entity in which a specific function will be ran if a certain body enters the radius.

In this scenario I have two entities:

A player with it's own collision shape in its tile.
An enemy with a large collision radius.

I have made sure that both of these CollisionShape2D's are on the same collision layer.

Within the enemy, attached to the Area2D (the aggro radius) I have this script:

extends Area2D

func _ready():
    connect("body_entered", self, "_on_body_enter")

func _on_body_enter(body):
    print("Test" + body.name)

Since the player's collision shape is a body I would assume that this would work but it doesn't. Is there anything extra I would need to do for this implementation?

in Engine by (30 points)

As a follow up question - what counts as a body for body_entered? Shouldn't two Area2D's with children CollisionShape2Ds on the same layer count?

With respect to what counts as bodies for collision, the nodes that have the word "Body" in their name count for body_entered(). I'm not entirely certain why it's set up like that. But the reason could be that the physics server and the system for detecting collisions are related.

2 Answers

0 votes
Best answer

The solution for this was to simply check for the area being entered rather than the body since I was only testing if two Area2D's collided essentially. Seems it was a dumb mistake.

extends Area2D

 func _ready():
     connect("area_entered", self, "_on_area_enter")

 func _on_area_enter(area):
     print("Test" + area.name)
by (30 points)
0 votes

I have a similar approach but don't use signals though it works.

func physics_process(delta):
         var Bodies = $Area2d.get_overlapping_bodies()
         for b in Bodies:
         if b.name == "Player":
                 print("Go to player")

Attach this to your area 2d if you don't want the hassle of signals
If your Player uses another area2d to get enemy aggressive then change var Bodies = get_overlapping_bodies() into var Areas = get_overlapping_areas()

Also the b.name = "Player refers to the name of your player area 2d or kinematic body

by (366 points)

Thank you for this solution!

I have a slight worry about it though - is it not much worse performance wise to check for colliding bodies every physics_process call rather than to wait for a signal?

It depends on you. I personally use this because of it's versatility. On the performance on the other hand, it is not fps eater. I think the most fps eater in your game is light and post procrssing

If the code frequently checks for collisions with get_overlapping_bodies(), then the performance will suffer.

Well, it's up to you, In my game personally, I use my solution but I didn't see any drastic performance suffer. Either way, you can use the signal method or collision check.

If performance suffers, on the other hand, you can just check the collision object surrounding if you press a certain key. I think this is the key aspect of reducing it's fps drop

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.