Help with complex collisions

Godot Version

4.2.1

Question

There’s a task I’m trying to figure out how to do that just has me stumped. I want to make a game where a player is shooting at a group of enemies. Both enemies and the attacks being launched can be of multiple different types and the different attacks should have different effects. How can I set the scene up so that it can be not just detected when an attack and an enemy collide, but also accurately apply the effect of the specific attack to the specific enemy that it collided with? It doesn’t seem like using on area entered or exited signals or making use of groups can provide the solution. Is there any way for a node to fetch or check against information from the node it collided with, the node that triggered its on area entered signal? (Please keep in mind that I am writing in C#)

start by setting up layers.
put player in layer 1, bullets in layer 2, enemies in layer 3.
then set layer detection, player collides with enemies but not bullet. enemy collides with player and bullet.

alternatively it’s a good idea to have a separate hitbox for bullets and attacks. this would be an Area3D to take bullets.

player would have one and each enemy will do too.

for detecting types of bullets there are many methods:

1 - you can use metadata. you add this to the bullet (the property at the bottom) metadata is part of the object class and can be a variable of any type, and it’s also safe.
you call get_meta(“bullet_type”, 0), where 0 is a value that will be returned if the meta is not found.

so when the enemy collides with a bullet, you get meta from body (the bullet)

2 - you probably thought about giving each bullet a different class, extending a base bullet class. but then you need to convert them to each class to check against it and that’s just bad.
instead use a base class and a method to take the type of bullet. you can extend this base class for new behaviours.
when the bullet collides, cast to bullet and call the method.


class Bullet : Area2D
int get_bullet_type()


class Rocket : Bullet

on enemy:

#when collision
var bullet : Bullet = body as Bullet#cast body to Bullet to new variable bullet
if bullet:#not null
    bullet.get_bullet_type()#and use a switch
#sorry if this is gdscript, just change the syntax for C#

this is basicaly the same as doing get meta but with a custom class.


no, that is the solution. there is no other solution.
on_area_entered function connected to the signal (remember to use events in C#, read the docs) then read the value and run a switch and depending on the value do a different thing.

this is a very basic question man. read the docs:

area_entered(area: Area2D)

Emitted when the received area enters this area. Requires monitoring to be set to true.

area_entered passes an area Area2D

body_entered(body: Node2D)

Emitted when the received body enters this area. body can be a PhysicsBody2D or a TileMap. TileMaps are detected if their TileSet has collision shapes configured. Requires monitoring to be set to true.

body entered passes a body Node2D. the same is true of Area3D.

these body and area arguments are passed by the Area2D signal and it’s the object it collided with.


if you are not experienced with C# and have only used it with unity, I recommend that you use gdscript instead since it’s just better in every way, and godot C# is for actual experts.

you probably thought about giving each bullet a different class, extending a base bullet class. but then you need to convert them to each class to check against it and that’s just bad.

Use abstract base bullet class with abstract method,
You just use this overridden method and take care self, with no checking what type of bullet hit.

Same you can do with c# interfaces,

If your bullet is more generic, you can add list of effects with dedicated classes

the syntax for C# would be:


Bullet bullet = body as Bullet;
if (bullet)
{
    switch(bullet.get_bullet_type())
        case 1://FIRE
            //take fire damage? set on fire?
            break;

In the end what was missing is I didn’t understand how exactly the passing of the Node worked and was able to make it work after figuring that out. Thank you for providing the missing piece there. (BTW, I’m using C# because I did actually have experience with it already before starting with Godot. Maybe ease up on the “are you an actual expert?” comments when talking with strangers yeah?)