Trigger 2D repel on overlap (2-D player combat issue)

Hey guys,

First real question on the forums here. I am working on a combat system similar to that of Smash brothers brawl and I cam upon an interesting issue. In Brawl, characters can’t occupy the same space but they also can’t stand on each others heads (exactly what I want). I have tried several options including triangular polygon colliders (a bit hacky) to my most recent attempt of having a 2-D box collider that isn’t a trigger to prevent pushing through characters with another box collider that is a trigger. This trigger detect overlap and pushes the character off depending on which way he is facing.

I think the ideal situation is to have two box colliders that are triggers and also repel each other on contact or overlap. I have messed with this as well and I can get them to repel from side to side but when you jump on a character it “jumps” to the edge of the collider and isn’t a smooth transition.

Sorry for the rant but if anyone has a solution, I would very much appreciate an opinion.

Please let me know if you need any additional information.

Thanks!

Well, the easiest way is to just push the one that’s above the other side ways (and a little up). If you use rigidbodies, just use normal colliders and if you collide with another player just do something like this:

// C#
float force = 20f; // adjust to your needs

void OnCollisionEnter2D(Collision2D col) 
{
    if (col.gameObject.tag == "Player")
    {
        var rel = rigidbody2D.position - col.rigidbody.position;
        if (rel.y > 0.5f) // if we are over the other
            rigidbody2D.AddForce(rel*force, ForceMode2D.Impulse); // push us away from the other player
    }
}

ps: don’t ask for “opinions” here :wink: This is NOT a forum.

edit
Just re-read your question. If you don’t want a to “agressive” push you can use

float force = 20f; // adjust to your needs
void OnCollisionStay2D(Collision2D coll)
{
    if (col.gameObject.tag == "Player")
    {
        var rel = rigidbody2D.position - col.rigidbody.position;
        if (rel.y > 0.5f)
        {
            rel.y = 0; // If you don't want to push him upwards.
            rel.Normalize();
            rigidbody2D.AddForce(rel*force);
        }
    }
}

Thanks a lot for the help. I ended up using a modified version of the script you provided because I wanted them to be able to pass through each other if enough force was applied. Here is what I ended up using:

public float force = 250f;
	
	void OnTriggerStay2D(Collider2D coll)
	{
		if (coll.gameObject.tag == "RepelBox")
		{	
			Rigidbody2D thisBody = GetComponentInParent<Rigidbody2D>();
			Rigidbody2D thatBody = coll.GetComponentInParent<Rigidbody2D>();
			var rel = new Vector2(thisBody.position.x, 0) - new Vector2(thatBody.position.x, 0);
			
			rel.Normalize();
			thisBody.AddForce(rel*force);
		}
	}