Checking direction in Area2D BodyEntered, and how to deal with delay in physics calculation

Godot Version

v4.5.stable.mono.official [876b29033]

Question

I want to ask both questions at once, since they are related. I’m implementing a mechanic where player can bounce on mob’s head. I’m handling it by adding an Area2D at the top of the mob, with this script attached to it:

public partial class MobBounceZone : Area2D
{
    public override void _Ready()
    {
        BodyEntered += OnBodyEntered;
        BodyExited += OnBodyExited;
    }

    private void OnBodyEntered(Node2D body)
    {
        if (body is CharacterBody2D characterBody && characterBody.Velocity.Y > 0)
        {
            var mobBounceComponent = body.GetNodeOrNull<MobBounceComponent>("MobBounceComponent");
            if (mobBounceComponent != null)
            {
                mobBounceComponent.WantToBounce = true;
            }
        }
    }
    
    private void OnBodyExited(Node2D body)
    {
        if (body is CharacterBody2D)
        {
            var mobBounceComponent = body.GetNodeOrNull<MobBounceComponent>("MobBounceComponent");
            if (mobBounceComponent != null)
            {
                mobBounceComponent.WantToBounce = false;
            }
        }
    }
}

And in theory, it works. Player script is properly informed and triggers jumping. Player script currently has jumping, horizontal movement, and gravity methods called on loop in _PhysicsProcess. If WantToBounce is true, player is allowed to jump. This information might be related to issue number two.

This implementation has two issues:

  1. Checking for velocity is not enough, since player can still enter the Area2D from the side while falling, and it will incorrectly trigger the jump.
  2. There is a significant delay in triggering the jump, and player character falls below the MobBounceZone, and enters the damage hitbox. It works flawlessly on low timescale, but not in real time.

Make the area narrower. As soon as area is entered, disable the damage hitbox.
If you insist you can check if area was entered “from above” by comparing player’s vertical positions in this and previous frame.

1 Like

I honestly didn’t think about disabling mob’s hitbox, I was thinking about doing something with the player, but I couldn’t figure out anything that wouldn’t potentially create issues. I think the delay situation is quite weird, but this solution is good enough in this case.

I don’t really understand how would comparing player’s vertical positions would work. My only idea is calculating how is player positioned relatively to the bounce zone, but I can’t think of anything that would work with perfect precision.

If player position is a point and zone collider is a box, it can be deduced if player entered the zone “from above” if line segment connecting player’s previous and current position intersects with line segment defined by zone collider’s top edge.

1 Like

I think I get it. But I think the entire problem can be bypassed. Because if player jumps from above, everything is fine. If player jumps from the side, as long as bounce zone is a little thinner than actual hitbox, player will get hit instead. But depending on how you handle hit reaction, player still can enter the bounce zone and jump will be triggered. I think the easiest route here would be disabling the bounce zone when player enters the hitbox, and enable it once player leaves the hitbox.

1 Like