Having in mind a platformer game with two players:

What's the best way to make collision between each body with the ground while not colliding between each body with each other, and making each other collide while attacking?

In other words:
Player-Ground (Collision)
Player-Other Player (No Collision)
Player Attacking - Other Player (Collision)

I have used layers and masks to solve this, but I need to make them collide when attacking.

I am thinking right now that the best way to solve this is using this scene hierarchy:

KinematicBody2D (Body){
-Sprite
-CollisionShape2D
-AnimationPlayer
}
-KinematicBody2D (Arm){
-CollisionShape2D
}

Then, while having two kinematic bodies, use the layers system.

I would like to know if I am heading the right way or there is a better way around.

Godot version 3.3.2
in Engine

+1 vote

It's overkill to have a separate KinematicBody2D only for army to get different collision.

Make a complete player with KinematicBody and it's collision to interact with environment.

For attacks, simple Area2D is more than enought. You can check collision of it (enable the node) only in the moment of attack.

You can even add another Area2D for different hitbox of a player:
KinematicBody that collide with environment can have bigger collision to make sure, that player is not half way in a wall/ground.

But because players often see hits that just barely scratched them as unfair, you can make it's hitbox smaller.

So layers are:
0 - environment
1 - hitbox

Kinematic body checks layer 0
Area2D Hitbox sits on layer 1
Area2D Arm check mask of layer 1 when attacking

by (195 points)
selected

This was a nice answer. But I solved in a slightly different way. I don't know if it is redundant this way but it worked:

KinematicBody2D{
-Sprite
-AnimationPlayer
-CollisionShape2D
-Area2D(Body){
-ColllisionShape2D
}
-Area2D(Attack){
-CollisionShape2D
}
}

Basically the first CS2D is for the environment, the second one is to signal incoming damage and the third one is to give damage.

(You should discard the player attacking itself though in script)