OK so i am working on a combat mechanism in my game but i need to check what enemy collided with my player's attack detector(an area 2d with a collision shape 2d node as a child). The area 2d is set to only detect enemy nodes but i don't know how i can access a variable(the knock-back variable, i need it to check how hard the enemy should hit. I am going to put this variable in every new enemy's script) from the collider's owner node's script.
How i can find out what collided with an area 2d and access a variable from its owner node?
- Edited
Are you familiar with the Area2D signals? The signal area_entered
is exactly what you want. But in this case I would suggest having the enemy dealing with the collision detection.
You can connect the signals in the following way:
1. Go to your enemy scene and click in the Collision Shape node
2. In the right side of your editor (assuming you are in the default template for Godot 3.4) right from the inspector tab there is the "node" tab.
3. Since I assume your enemy is also a Collision Shape with an Area2D it must have the area_entered
signal there.
4. Right click it and connect it to itself (with the Collision Shape that has the enemy script).
5. It will create a function along the lines with _on_Enemy_area_entered(area)
You can read more about using signals in this documentation article.
Inside this created function you can check if the area entered in the Enemy's Area2D is the player. I usually do this adding the player scene or player hitbox to a "player" group (you can do this going to your player scene -> Node tab in the right side of the editor -> group -> write "player" and add it), then your function would look something like:
func _on_Enemy_area_entered(area):
if area.is_in_group("player"):
area.take_damage(knock_back_value)
Where knock_back_value
would be a variable inside the enemy script and take_damage
a method inside the player script that would apply the knock back how you want.
@bored_paramecium said: Are you familiar with the Area2D signals? The signal
area_entered
is exactly what you want.You can connect the signals in the following way: 1. Go to your enemy scene and click in the Collision Shape node 2. In the right side of your editor (assuming you are in the default template for Godot 3.4) right from the inspector tab there is the "node" tab. 3. Since I assume your enemy is also a Collision Shape with an Area2D it must have the
area_entered
signal there. 4. Right click it and connect it to itself (with the Collision Shape that has the enemy script). 5. It will create a function along the lines with_on_Enemy_area_entered(area)
You can read more about using signals in this documentation article.
Inside this created function you can check if the area entered in the Enemy's Area2D is the player. I usually do this adding the player scene to a "player" group (you can do this going to your player scene -> Node tab in the right side of the editor -> group -> write "player" and add it), then your function would look something like:
func _on_Enemy_area_entered(area): if area.is_in_group("player"): area.take_knock_back(knock_back_value)
Where
knock_back_value
would be a variable inside the enemy script andtake_damage
a method inside the player script that would apply the knock back how you want.
Of course i know how to use the area 2d signals. But that's not the main concern. I have the enemy as a kinematic body 2d with a collision shape 2d as a child. I don't get how the "area.take_knock_back(knock_back_value)" line works. Can you tell me what this line does and how it works? I am still learning Godot and Gd-script. Also you left me on a cliff hanger on one of my previous questions. I still haven't figured out how i am gonna go about on implementing wall-jump. But that's not the main topic right now.
- Edited
The line works because the area
parameter passes the Area2D object that entered in the area of the signal emitter, in my example it would be the player. I assume you have a function in the player script that deals when they receive damage, that function would be take_damage(value)
. Since you passed the player object as a parameter to the _on_Enemy_area_entered(area)
you can access its "inner function" (a method) with the dot .
passing the enemy's knock_back
as a parameter. Basically what you are doing is calling the take_damage()
function in the player script from the enemy script.
Are you familiar with OOP (Object Oriented Programing)? If not, it would be good to have an overview about it, since it's wildly used in Godot, game and software development in general.
You didn't mention your enemy was a Kinematic Body, so I assumed it was an Area2D. But this is minimal, the only change you need to make in the instructions I passed you is that now the Player's Area2D should be the one detecting the overlap. You can use the body_entered
signal from the Area2D to detect when the enemy's body enters in the Player's Area2D, then in the _on_Player_body_entered(body)
something like:
func _on_Player_body_entered(body):
if body.is_in_group("enemies"):
# knock_back_damage is a variable in your enemy script
var damage = body.knock_back_damage
# take_damage is a function in your player that deals with the damage taken
take_damage(damage)
In other words, you can access a variable of other object using the .
.
I didn't continue with your answer in the other topic because you accepted an answer and because I don't know what more I could do. I would probably need to re implement all your code locally and run tests by myself, something I do not have time to perform.