ColorfulYoshi
ColorfulYoshi

Reputation: 121

Examples of using body_entered and body_exited in Godot 3D (version 3.4.4)

I am trying to make a teleport part, so I need to detect when Body collides with area. I tried to use body_enter/body_entered and body_exit/body_exited, but I do not know how exactly they work and where do I need to insert them. Can I have example codes of using it? My nodes path:

RigidBody
├ CollisionShape
├ MeshInstance
├ Area
├ ├ CollisionShape

Upvotes: 3

Views: 18393

Answers (1)

Theraot
Theraot

Reputation: 40220

Scene tree structure

First of all, if you want two things to collide you probably want them to be siblings. Not one Node child of the other. This is because Spatials are placed relative to their parent. Said another way: when an Spatial moves, its children move with it.


Enable monitoring

Second, you want to make sure that the Node that will detect the collision is able to do it. In the case of a RigidBody and an Area, the Area will detect the RigidBody, and for that it must have monitoring to be true This is the default. Thus, unless you have been messing with it, you need to do nothing.


Layers and masks

Third, you want the layers and masks to overlap. In particular, you want the collision_mask of the Area to have bits in common with the collision_layer of the RigidBody. By default, they come with the first bit set, so this is also satisfied by default unless you have been messing with it.


SIGNALS

Fourth, you need to connect the "body_entered" signal of the Area. You have two ways to do that:

  • Using the editor:

    Have the Area selected in the Scene panel (on the left by default), and then go to the Node panel (on the right by default) and then to the Signals tab.

    There you should find "body_entered(body:Node)". Double click it. Or select it and then click the "Connect…" button at the bottom, or press enter.

    Godot will ask you to select the Node you will connect it to. You can connect it to any Node on the same scene that has a script attached beforehand. I suggest to connect it to the Area itself.

    Godot will also allow you to specify the name of the method that will handle it (by default the name will be _on_Area_body_entered).

    Under "advanced" you can also add extra parameters to be passed to the method, whether or not the signal can/will wait for the next frame ("deferred"), and if it will disconnect itself once triggered ("oneshot").

    By pressing the Connect button, Godot will connect the signal accordingly, creating a method with the provided name in the script of the target node if it does not exist.

  • From code:

    To connect a signal from code you use the connect method. See also disconnect and is_connected.

    So you can, use the connect method to connect the "body_entered" signal, like this:

    func _ready() -> void:
        connect("body_entered", self, "_on_Area_body_entered")
    
    func _on_Area_body_entered(body:Node) -> void:
        pass
    

    This code is intended to work in a script attached to the Area itself. It is also possible to call connect from a Node to another. Please note that we are passing the name of the method we want to connect as parameter to the connect method, and thus it can be whatever you want.

    The connect method has optional parameters to specify extra parameters, or if you want the connection to be deferred or oneshot.

To reiterate: simply adding a method won't work, you need to connect the signal to it. And there is no special name for the method, it can have any name you choose.


With that done, the method should execute when the RigidBody overlaps the Area.

Upvotes: 6

Related Questions