1
\$\begingroup\$

I have a class for a projectile defined like this:

namespace godot
{

class Projectile : public RigidBody2D
{
    // Godot structure
private:
    GDCLASS(Projectile, RigidBody2D);

public:
    virtual void _physics_process(double delta) override;

    Projectile();
    ~Projectile();

};
}

Then I have a class for anything that can be shot:

class ShootableObject : public RigidBody2D
{
    // Godot structure
private:
    GDCLASS(ShootableObject, RigidBody2D);

public:
    virtual bool receiveDamage(double damage);
    
    ShootableObject();
    ~ShootableObject();

};

This is how I register them with the engine:

#include "Projectile.h"
#include "ShootableObject.h"

void initialize_example_module(godot::ModuleInitializationLevel p_level)
{
    if (p_level != godot::MODULE_INITIALIZATION_LEVEL_SCENE)
    {
        return;
    }
    godot::ClassDB::register_class<godot::Projectile>();
    godot::ClassDB::register_class<godot::ShootableObject>();
}

Then for collisions, I do this in the projectile class:

void Projectile::_physics_process(double delta)
{
  TypedArray<Node2D> colliders = get_colliding_bodies();
  bool hit = false;
  for (int i=0; i<colliders.size(); ++i)
  {
    Object* o = colliders[i];

    if (PhysicsBody2D* body = Object::cast_to<PhysicsBody2D>(o))
    {
      if (ShootableObject* shootable = Object::cast_to<ShootableObject>(body))
      {
        if(shootable->is_inside_tree())
          shootable->receiveDamage(props.damage);
      }
      hit = true;
    }
  }

  if (hit)
  {
    queue_free();
  }
}

The problem is, the cast_to always returns a pointer, even if two projectiles hit each other. That subsequently causes crash when trying to call receiveDamage on something that is not ShootableObject.

I can avoid the issue by doing this, but that's just plain stupid:

        if (body->get_class() != "ShootableObject")
        {
          return;
        }

Why is this happening? I tried to enable RTTI in my build in case there was a problem with that (shouldn't be) and that did not help. Is there something wrong with those class definitions?

\$\endgroup\$
2
  • \$\begingroup\$ Two things I would test, but which will not answer the question: what if you use a dynamic_cast instead of obejct::cast_to (it appears it is what godot's code is doing under the hood), and what if you cast the o to shootable instead of casting body to shootable? \$\endgroup\$
    – Vaillancourt
    Nov 5, 2022 at 22:05
  • \$\begingroup\$ What comes to mind is to use is_instance_valid. However I didn't find examples using that, and for what I'v seen I believe that what you are doing should work. \$\endgroup\$
    – Theraot
    Nov 6, 2022 at 6:58

1 Answer 1

0
\$\begingroup\$

This was a bug that was still occurring in Godot 4.0 (I tested it a few months ago) and is no longer occurring in Godot 4.1.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .