Godot Version
4.3
Question
I’m attempting to recreate the behavior of player collision from 2D fighting games through a pushbox system. Pushboxes allow players to push each other while preventing them from standing on one another. My implementation is an Area2D that separates the characters based on the overlap of their collision shapes.
extends Area2D
class_name Pushbox
@onready var CollisionShape : Shape2D = $"Pushbox Shape".get_shape()
func _physics_process(_delta: float) -> void:
var overlapping_areas : Array = get_overlapping_areas()
for i in overlapping_areas.size():
var overlap = overlapping_areas[i]
if overlap is Pushbox:
var colliding_pushbox : Pushbox = overlap
var opposing_player : CharacterBody2D = colliding_pushbox.get_parent()
# Defines the left and right extents of the player's pushbox collision shape
# and the opposing player's pushbox collision shape.
# Player pushbox left/right
var self_pushbox_left : float = global_position.x - (CollisionShape.size.x / 2)
var self_pushbox_right : float = global_position.x + (CollisionShape.size.x / 2)
# Opposing player pushbox left/right
var colliding_pushbox_left : float = colliding_pushbox.global_position.x - (colliding_pushbox.CollisionShape.size.x / 2)
var colliding_pushbox_right : float = colliding_pushbox.global_position.x + (colliding_pushbox.CollisionShape.size.x / 2)
# Finds the overlap between the two collision shapes.
var right_overlap : float = abs(self_pushbox_right - colliding_pushbox_left)
var left_overlap : float = abs(colliding_pushbox_right - self_pushbox_left)
# The position adjustment will be used to push the players apart.
var position_adjustment : float
# Whichever overlap is the smallest out of the two will be used as the position adjustment.
if (right_overlap <= left_overlap):
position_adjustment = right_overlap
elif (left_overlap <= right_overlap):
position_adjustment = -left_overlap
# Finally, the position adjustment is halfed.
position_adjustment *= 0.5
opposing_player.global_position.x += position_adjustment
It works somewhat as intended; the players do indeed push each other apart, preventing them from standing on each other’s heads. However there is an inconsistent and I guess squishy(for lack of a better word) effect to this:
Notice how only one pushbox is able to squeeze the other into clipping through the wall, also notice how they marginally overlap, which is not intentional. See also:
Ideally, there would be no overlapping like this. I’ve tried a lot to fix this but I can’t seem to wrap my head around it, and I’d really appreciate some help.