How to create a knockback that works for 2D ?

Good day fellow Unity Developers

First off, my programming is in C# but understand java script fairly well so feel free to add your answer if your a java script coder.

So I am working on an Exam project which is a 2D game. I am currently struggling to apply the perfect knock back. So first off I know there is a lot of answers to this question but most of them wont work for what I am searching.

Keep in mind that I know this is for one direction only as I am just testing to get the knock back correctly. My player knocks up correctly but after a few split seconds just stop on the x-axis and I think I know why but I need a solution.

Here is my code to addforce.

void Update () 
	{

        if (0.2f > timer)
        {


            timer += Time.deltaTime;

            rb2d.AddForce(new Vector3(-500f, 80f, transform.position.z));




            Debug.Log(timer);
        }
        else if (0.2f < timer)
        {
            
        }

       
        

	}

	void OnTriggerEnter2D(Collider2D other)
	{
        foreach(GameObject g in totPlay)
		if (g.gameObject.name == other.name) 
		{
            
            
            knockbackDir = other.GetComponent<Transform>().position;
            rb2d = other.GetComponent<Rigidbody2D>();
            timer = 0;
            
            testOneUse = true;}
}

Since this is a game that support multiple players I had to run the foreach. Back to business
This is my movement script.

void Update()
{
moveVelocity = 0f;

        if (Input.GetAxisRaw ("Horizontal") < 0)
        {
            
            moveVelocity = -moveSpeed;
            
        }

        if (Input.GetAxisRaw("Horizontal") > 0)
        {
            
            moveVelocity = moveSpeed;

            
        }

GetComponent<Rigidbody2D>().velocity = new Vector2 (moveVelocity, GetComponent<Rigidbody2D>().velocity.y);
}

So I noticed that moveVelocity is always 0 unless the player press the move buttons. I think this might be my problem. Since the moment force is applied to my player it changes back to 0 or which ever button the player press to move, interrupting the addforce command meaning that the X-axis returns to 0, moveSpeed or -moveSpeed almost immediately after the addforce command.

Also I do not like the idea of subtracting the enemy position from the player position because the subtraction changes Y-axis to almost 0 if both the player and enemy is on the same ground. My solution to this was adding my own values to the addforce.

So Mr or Ms Unity developer can you help me ?
Thank you for your time

Setting the velocity directly overrides any current force on the Rigidbody2D. This means that if you move by setting velocity, any and all AddForce calls will immediately be canceled. Some suggestions for solving this would be:

  • Move by using AddForce
  • Don’t set the velocity when the player is being knocked back
  • Do the knockback by moving the rigidbody directly (a coroutine would be easier than what you’re doing now)

I think the second one is most in line with the standard way knockback is handled in games - getting to move forward while you’re getting knocked back kinda defeats the purpose of a knockback.

The easiest way to do this would be to search for your movement script in the OnTriggerEnter, and tell it to get knocked back if you find it, instead of knocking it back externally. You’re looking for GetComponent to do that:

void OnTriggerEnter(Collider other) {
    MovementScript mover = other.GetComponent<MovementScript>(); // or whatever you called the movement script

    if(mover != null) {
        Vector2 knockBackDir = (mover.transform.position - transform.position).normalized;

        mover.GetKnockedBack(knockBackDir); //@TODO: implement this
    }
}

Rigidbody2D.Addforce now supports Impulse ForceMode.

So, in pseudo

OnCollisionEnter

if(other == Whatever object)

other.contacts //Collision2D contacts to detect the point which was struck.

rb2D.Addforce → Something small at the contact point Through the object centre with a small Impulse.