0
\$\begingroup\$

My player will basically be pushed back forever after colliding with an enemy. I have tried changing the mass of the player to like 100, but it still does the same thing. The force that pushes the player is already 1f, so there must be something wrong with the code. Code:

[SerializeField] private LayerMask platformsLayerMask;

[SerializeField] private Rigidbody2D rb;

public float MovementSpeed = 100f;

public float JumpingHeight = 100f;

[SerializeField] private BoxCollider2D bc;

public float fallMultiplier = 2.5f;
public float lowJumpMultiplier = 2f;

[SerializeField] private Animator anim;

private enum State {idle, running, jumping, falling, hurt}
private State state = State.idle;

private Collider2D coll;

[SerializeField] private int cherries = 0;
[SerializeField] private Text cherryText;

[SerializeField] private float hurtForce = 10f;

void Awake()
{
    rb = transform.GetComponent<Rigidbody2D>();
    bc = transform.GetComponent<BoxCollider2D>();
    coll = transform.GetComponent<Collider2D>();
    anim = transform.GetComponent<Animator>();
}

void Update()
{
    if(state != State.hurt)
    {
        Movement();
    }
    VelocityState(); //referencing the void VelocityState
    anim.SetInteger("state", (int)state);
}


void Movement()
{
    float vDirection = Input.GetAxis("Vertical");
    if (coll.IsTouchingLayers(platformsLayerMask) &&  vDirection > 0)//the player is only able to jump if it is on the ground
    {
        rb.velocity = new Vector2(rb.velocity.x, JumpingHeight);
        Debug.Log("Jumping");
        state = State.jumping;
    }

    float hDirection = Input.GetAxis("Horizontal");

    if (hDirection < 0)
    {
        rb.velocity = new Vector2(-MovementSpeed, rb.velocity.y);
        Debug.Log("Going Left");
        transform.localScale = new Vector2(-1, 1); //flips sprite
    }
    else
    {
        if (hDirection > 0)
        {
            rb.velocity = new Vector2(+MovementSpeed, rb.velocity.y);
            Debug.Log("Going Right");
            transform.localScale = new Vector2(1, 1); //flips sprite
        }
        else
        {
            //no keys pressed
            rb.velocity = new Vector2(0, rb.velocity.y);
            Debug.Log("No key pressed");
        }
    }
    if (rb.velocity.y < 0) //reponsive jumping and falling
    {
        rb.velocity += Vector2.up * Physics2D.gravity.y * (fallMultiplier - 1) * Time.deltaTime;
    }
    else if (rb.velocity.y > 0 && vDirection > 0)
    {
        rb.velocity += Vector2.up * Physics2D.gravity.y * (lowJumpMultiplier - 1) * Time.deltaTime;
    }

}




private void VelocityState() //for switching states for animations
{
    if(state == State.jumping) //when jumping, if the player starts falling, switch to falling animation.
    {
        if(rb.velocity.y < 0.1f)
        {
            state = State.falling;
        }
    }
    else if(state == State.falling) //when falling, if the player touches the platform, switch to idle. 
    {
        if (coll.IsTouchingLayers(platformsLayerMask))
        {
            state = State.idle;
        }
    }
    else if (state == State.hurt)
    {
        if (Mathf.Abs(rb.velocity.x) < .1f)
        {
            state = State.idle;
        }
    }
    else if (Mathf.Abs(rb.velocity.x) > Mathf.Epsilon) //if running, switch to running animation. 
    {
        //moving
        state = State.running;
    }
    else //if it is not everything above, idle
    {
        state = State.idle;
    }
}

private void OnTriggerEnter2D(Collider2D collision) //cherries
{
    if (collision.tag == "Collectible") 
    {
        Destroy(collision.gameObject);
        cherries += 1;
        cherryText.text = cherries.ToString();
    }
}

private void OnCollisionEnter2D(Collision2D other) //enemies 
{
    if (other.gameObject.tag == "Enemy")
    {
        if (state == State.falling)
        {
            Destroy(other.gameObject);
        }
        else
        {
            state = State.hurt;
            if(other.gameObject.transform.position.x > transform.position.x)
            {
                //enemy is on my right therefore I should be damaged and moved left
                rb.velocity = new Vector2(-hurtForce, rb.velocity.y);
            }
            else
            {
                //enemy is on my left therefore I should be damaged and moved right
                rb.velocity = new Vector2(+hurtForce, rb.velocity.y);
            }
        }
    }
}
\$\endgroup\$
1
  • \$\begingroup\$ When you're in your hurt state, you're skipping the movement method that sets your horizontal velocity. Did you mean to replace this behaviour with something that would slow you to a stop when hurt? \$\endgroup\$
    – DMGregory
    Mar 11, 2020 at 12:36

2 Answers 2

1
\$\begingroup\$

You should not change the velocity of the RigidBody directly.

Try using AddForce instead.

if(other.gameObject.transform.position.x > transform.position.x)
{
    rb.AddForce(-hurtForce,rb.velocity.y,0,ForceMode.Acceleration);
}
\$\endgroup\$
1
  • \$\begingroup\$ This is definitely the first thing you should change and observe the effects of @SkullCutter \$\endgroup\$
    – Natalo77
    Mar 11, 2020 at 11:40
0
\$\begingroup\$

Your problem is here:

if(state != State.hurt)
{
    Movement();
}

Movement is the only code that modifies your object's velocity. Without that, your object will coast up to the whims of physics.

For a knockback, we want a bit of sliding, but not an unlimited amount. So let's add some drag.

if(state != State.hurt)
{
    Movement();
} else {  // You could also add a time condition here to put the brakes on after a delay.
    var velocity = rb.velocity;
    velocity.x *= 0.9f; // Quick and dirty deceleration.
    rb.velocity = velocity;
}

Remember to put this in FixedUpdate to ensure you get consistent behaviour regardless of the framerate.

\$\endgroup\$

You must log in to answer this question.