Attention | Topic was automatically imported from the old Question2Answer platform. | |
Asked By | tyo |
I have two Area2Ds.
The first area, which I call DamageArea, is the child of the player’s Kinematic Body, and deals with taking damage from enemies, enemy attacks, and hazards. Each of these types of objects have their own collision layers, which are masks for this Area. The Area itself is of course on the Player layer.
The other, which I call Sight, is the child of every enemy’s Kinematic Body, and deals with detecting the player when the player enters this area. Effectively, it’s the enemy’s line of sight. It’s on its own collision layer, “Uninteractables,” which is a layer which should not interact with anything. It detects the player by having the player collision layer as its only collision mask.
Now, by the Godot API,
collision_layer: This describes the layers that the object appears in. By default, all bodies are on layer 1.
collision_mask: This describes what layers the body will scan for collisions. If an object isn’t in one of the mask layers, the body will ignore it. By default, all bodies scan layer 1.
By this logic, I thought the interaction between these two Area2D’s would be that Sight detects whenever DamageArea enters Sight. DamageArea, meanwhile, would not detect Sight at all.
However, this isn’t what I am observing.
Whenever DamageArea enters Sight, Sight does detect it, but it also causes the player to be damaged. But, DamageArea does not have the “Uninteractables” mask. Shouldn’t this not be the case?
Here’s relevant code.
First, for Sight:
extends Area2D
var sight;
onready var host = get_parent();
func _ready():
connect("area_entered", self, "on_area_entered");
connect("area_exited", self, "on_area_exited");
pass
func on_area_entered(area):
if(host.state == 'attack'):
return;
var other = area.get_parent();
if(other.tag == "player"):
host.target = other;
host.state = 'chase';
pass
func on_area_exited(area):
if(host.state == 'attack'):
return;
var other = area.get_parent();
if(other.tag == "player"):
host.target = null;
host.state = 'default';
pass
Now, DamageArea:
extends Area2D
onready var host = get_parent();
func _ready():
connect("area_entered", self, "on_area_entered");
pass
func on_area_entered(area):
#if(("sight" in area)):
# return;
var object = area.get_parent();
if(host.state != 'hurt'):
host.velocity.x = 0;
host.velocity.y = 0;
host.states['hurt'].hurt_timer = 7;
host.state = 'hurt';
host.hp -= object.damage;
if(object.position.x >= host.position.x):
if(host.Direction != 1):
host.scale.x = host.scale.x * -1;
host.Direction = 1;
else:
if(host.Direction != -1):
host.scale.x = host.scale.x * -1;
host.Direction = -1;
pass
Note the commented out segment
#if(("sight" in area)):
# return;
The code works perfectly fine with this included, as the Sight area is the only node in my project with “sight” as a variable, which confirms that this is indeed the issue. However, I’d rather fully understand how Areas work than implement this workaround. Is my original understanding of Area2D correct and I’m just missing something, or is this behavior intended?
Thanks in advance!