Knockback is not consistent

Hello,

I am trying to get a knockback to work for my player. I am trying to implement a simple slammer (box) that shoots out from left to right when the player triggers a collider. If the slammer hits the player, it should knock them backwards (to the right).

I have watched all the videos I could find, read lots of threads and tried several different ways of implementing knockback. Unfortunately, I am getting very inconsistent results. Sometimes the player is knocked back as expected, but at other times the slammer knocks them almost off the screen or just seems to push them.

I have posted my code below and as you can see from all the commented out lines, I have tried a number of different approaches. This is on the Player.cs script:

    public void OnCollisionEnter2D(Collision2D other) {
        if (other.gameObject.CompareTag("Slammer")) {
            //var magnitude = 5000;
            // calculate force vector
            //var force = transform.position - other.transform.position;
            // normalize force vector to get direction only and trim magnitude
            //force.Normalize();
            //RB.AddForce(-transform.right * magnitude, ForceMode2D.Force);
            //RB.velocity = new Vector2(500f, 5f);
            DoKnockback();
        }
    }

    public void DoKnockback() {
        //StartCoroutine(DisablePlayerMovement(_knockbackLength));
        //RB.velocity = new Vector2(-FacingDirection * _knockbackForce, 0);
        //RB.AddForce(new Vector2(-FacingDirection,0) * _knockbackForce, ForceMode2D.Impulse);
        //transform.position = Vector2.MoveTowards(transform.position, new Vector2(transform.position.x - 20f, transform.position.y), 3 * Time.deltaTime);
        RB.velocity = new Vector2(_knockbackForce, RB.velocity.y);
    }

    //private IEnumerator DisablePlayerMovement(float time) {
    //    stopMovement = true;
    //    yield return new WaitForSeconds(time);
    //    stopMovement = false;
    //}

The slammer is configured as follows:


SlammerHorizontal has a box collider to detect the player is in the danger zone and the controller script
Smasher has the sprite renderer for the slammer box and a rigidbody2d set to Kinematic
Killer has the box collider for Smasher - this gets enabled / disabled depending on the state
SlamTarget is a Transform that the Smasher moves towards when triggered.

Fairly simple setup, but for some reason I cannot get it to knock the player back consistently each time.

Does anyone have any advice or can point me in the right direction?

Many Thanks,

J

If you need a consistent knockback, take over control of the player for a short period of time when the knockback occurs and move them through the arc you want, disabling all user input during that time.

You can optionally blend out the motion as it nears the end of the curve, so that the player’s actual inputs begin to affect them again.

Be sure to do ALL work in FixedUpdate() (because it is physics-timing-related), and also be sure to move the player ONLY with the .MovePosition() method on the Rigidbody2D, otherwise you will miss collisions and glitch into things.

Hi Kurt,

Thank you for your response. I have read the documentation on MovePosition and it works with a kinematic rigidbody. My player uses a dynamic rigidbody. I have implemented it anyway, and it seems to work most of the time, but glitches sometimes (player seems to go through collider). I did try to change the rigidbody to kinematic when the player triggers the slammer, but that shoots the player up in the air.

Do you have any suggestions.

Many Thanks,

J