Can player script determine if player collides with an Area2D

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By colonelkurtz

I’m trying to wrap my head around the node system, but I’m getting stuck at something that seems simple. Building a top-down 2D game, I have a player character that can move about (Parent Node with KinematicBody2D, CollisionShape2D, Sprite, and Camera). The script is attached to the KinematicBody2D.

I’m trying to make a basic NPC interaction, where, when close enough and upon clicking a button, the player character will “interact” with the NPC/object. The reason I’m trying to have the detection behavior happen in the character script is that I want to pause character motion (speed 0 or similar) when interacting.

Everything I’ve found in regards to Area2D area_entered seems to require the detection and script to be on the Area2D (NPC) object. Could I (and how) implement the detection in the player script?

:bust_in_silhouette: Reply From: Socrates

Just make an Area2d with a collision shape attached to the KinematicBody2d. Then (making sure the collision mask is set to the same collision layer the npc’s Area2d is on). In the player script create a variable referring to the Area2d and connect the Area2d to a method you want to call

`area2d.connect(“area_entered”, self, “name of method you want to call”)

Then you just have to write the method that’s called when the overlap between the npc’s and player’s Area2ds occurs.

(btw the connect() method is how you set up signals which are useful and the usual way to create interactions between different scenes)

Socrates | 2018-03-07 02:17

I tried adding this and it failed to work (I’m not sure if the collision layers are the same). Right now, the Player character is set up as:

Player (empty node)
  KinematicBody2D (script attached here)
    Sprite
    CollisionShape2D
    Camera2D
    Area2D
      CollisionShape2D

The interactable objects are curently set up as:

Node 
  Sprite
  StaticBody2D 
    CollisionShape2D

My player script calls:

func _ready():
     Area2D.connect("area_entered", self, "interact")

func interact(object):
     print("interact")

Is something obvious missing from this setup?

colonelkurtz | 2018-03-07 04:23

I think your interactable object might need an Area2d of its own with a collision shape. Also, I have the line $Area2D/CollisionShape2D.disabled = false in my own code, but i forget why i did this and am not sure it’s necessary.

Edit: I forgot there is also a “body_entered” signal that will be emitted when a physics body, such as the StaticBody2D enters the area.

Socrates | 2018-03-07 05:42

:bust_in_silhouette: Reply From: colonelkurtz

I took Socrate’s answer, did some more research, and came up with this. I’m writing it down because I was searching far too long for a simple solution on how to implement 2D character interaction, collision detection, NPC interaction, or whatever you want to call it:

Node setup:

Player
 KinematicBody2D
   CollisionShape2D
 Area2D
   CollisionShape2D

NPC
 Area2D
   CollisionShape2D
 KinematicBody2D
   CollisionShape2D

From Player’s Area2D Nodes, I’ve area_entered() and area_exited() connected to the player character script, which is attached to the Player’s KinematicBody2D.

The following simple code detects the NPC’s root name and sets an interact variable.

func _on_Area2D_area_entered(area):
   parent = area.get_parent().get_name()
   canInteract = true #this is for another function's use

func _on_Area2D_area_exited(area):
   parent = null
   canInteract = false

Super simple. I’m sure there’s a better way to handle this, but it took me way too longer as a Godot beginner to figure this out (Godot 3.x changed its code structure a little, and the good tutorials are all on 2.x), so hopefully this helps jumpstart another newbie’s Godot experience.