0 votes

KinematicBody2D continues to collide via GetSlideCollision with entities that have been removed from the tree.

I have a strange problem. I have a 2D game with poolable, colliding KinematicBody2Ds (C#). When a KinematicBody2D dies, it is removed from tree, has its layer/mask set to 0, moved to a random position far away, etc. However, after the player has collided with and killed another body, every second or 2 the engine will think they are still colliding and damage the player.

Here is my collision code in my KinematicBody2D. Somehow it is confused and colliding with things not in the scene tree, not in the same position, and with different collision masks/layers.

public override void _PhysicsProcess(float delta)
{
    base._PhysicsProcess(delta);
    processCollisions();
}
private void processCollisions()
{
    for (int i = 0; i < this.GetSlideCount(); i++)
    {
        KinematicCollision2D collision = this.GetSlideCollision(i);
        Godot.Object other = collision.Collider;
        takeDamageFrom(other);

        Collidable otherCollidable = other as Collidable;
        if (otherCollidable != null) otherCollidable.takeDamageFrom(this);
    }
}

What happens when the life <= 0:

  virtual public void Kill()
  {
    SetPhysicsProcess(false);
    SetProcess(false);

    if (GetParent() != null) //might be called multiple times
    {
        GetParent().RemoveChild(this);
        Globs.Pools.add(ScenePath, this);
        EmitSignal(nameof(died));
    }

    CollisionLayer = 0;
    CollisionMask = 0;


    float r1 = (float) Globs.rand.NextDouble();
    float r2 = (float) Globs.rand.NextDouble();
    this.GlobalPosition = new Vector2(r1, r2) * -1000000 - new Vector2(-100, -100);

    //kill all components
    List<Component> components = getComponents();
    foreach (Component c in components)
    {
        c.OwnerKilled();
    }
}

Edit: I've tried debugging when one of these ghost collisions occur. I've seen the other Entity is colliding with player, and it's GetParent() call is not null. I'm not sure why it's not being removed.

Edit: If I call QueueFree() in Kill(), then it is STILL COLLIDING! but it will have a NullReferenceException when trying to use collision.Collider for things.

Edit: I swear it wasn't working earlier, but if I just check to make sure the collision is OK now, then it appears to be working (whether pooling or calling QueueFree()).

        bool badCollision = nOther == null || !nOther.IsInsideTree();
        if (!badCollision)
        { Collidable otherCollidable = other as Collidable; ... }

I have a feeling it might stop working so im gonna wait to accept the answer.

in Engine by (684 points)
edited by

Please log in or register to answer this question.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.