How can I use Godot's "is_in_group" method in a C# script?

Viewed 129

I am new to both Godot and C#, so I will try to be as clear as possible in my question.

I am trying to recreate Pong by following a tutorial that uses GDScript (not otpimal, but it forces me to "translate" stuff from one language to the other). The problem I'm currently facing is that I want to verify if the ball is hitting the racket or the walls by using groups. For this, the MoveAndCollide() method is both moving the ball and returning the colliding KinematicBody2D object in this "collision" variable.

Godot.KinematicCollision2D collision = MoveAndCollide(direction * delta);
    if (collision != null)
    {
        direction = direction.Bounce(collision.Normal);
        if (collision.Collider.IsInGroup("rackets") //the script doesn't recognize the method IsInGroup, so this line does not work
        {
            //change the ball's speed
        }
    }

In the tutorial, the author uses the method is_in_group, but it seems to not exist in the mono version.

1 Answers

The issue is that IsInGroup is declared on the Node class, but collider is defined as Object. So you need to cast it to Node (PhysicsBody2D is probably as close to the actual type that you can get).

This happens on a technicality: The physics server only knows that the physics body is represented by an Object, and it does not care if it is a Node or not (which can be useful if you work with the API at a lower level). Yet, presumably you are not doing anything of the sort, so go ahead and cast it:

if (((PhysicsBody2D)collision.Collider).IsInGroup("rackets"))
{
    //change the ball's speed
}

With that said, just in case, you could use a safe pattern, since the above code will throw if the type does not match. I'm going to encourage to check only once by introducing a variable:

var body = collision.Collider as PhysicsBody2D;
if (body != null && body.IsInGroup("rackets"))
{
    //change the ball's speed
}

C# offers more compact syntax for null checks, however… Godot does not null references to Nodes when they are freed, instead they mark the instance as invalid. And as far as I can tell, Godot does not overload equality. You can check for null and invalid instances at once with IsInstanceValid:

var body = collision.Collider as PhysicsBody2D;
if (Object.IsInstanceValid(body) && body.IsInGroup("rackets"))
{
    //change the ball's speed
}

By the way, you could directly check and cast to KinematicBody2D, RigidBody2D or StaticBody2D instead of PhysicsBody2D if you know what you expect.

Related