Search Unity

Push enemy with physics (spell casting push)

Discussion in 'Physics' started by Thiem, Aug 26, 2019.

  1. Thiem

    Thiem

    Joined:
    Jun 30, 2014
    Posts:
    20
    I'm playing around with a top-down pvp spell casting game. I want some spells to push other players, like a force wave push or whatever. Now, I'm using the rigidbody on a player to control this player, like so:

    Code (CSharp):
    1. float horiz = Input.GetAxisRaw("Horizontal");
    2.         float vert = Input.GetAxisRaw("Vertical");
    3.         Vector3 moveDir = new Vector3(horiz, 0f, vert).normalized;
    4.         Vector3 targetMoveAmount = moveDir * speed;
    5.         moveAmount = Vector3.SmoothDamp(moveAmount, targetMoveAmount, ref smoothMoveVel, SmoothTime);
    6.         rb.velocity = moveAmount + Vector3.up * rb.velocity.y;
    The SmoothDamp part is just to add a kind of acceleration.
    So the problem is, if a player is hit by a fireball or whatever, I would usually just go something like

    enemyTarget.GetComponent<Rigidbody>().AddForce(forceDir * 750f);

    But in the last line of code above with the movement, I'm constantly (FixedUpdate) setting the velocity, so whatever force I added from the fireball will be overwritten with the movement speed.

    I have considered:
    • Using AddForce to control movement, instead of just setting the velocity, but it just kind of feels like the players skate around on ice. I could set the added force fairly high, and then clamp the velocity, to make it feel less like skating. But then I would also have to increase the spell force, so that you can't just move in the opposite direction and stop almost right away. And if you then don't touch the movement, you're thrown into space.
    • I could disable movement controls for, say, 0.5 seconds after adding the spell force, but this feels like a strange hack, and I'm overly fan of that approach. And then after 0.5 seconds, you'd stand completely still, no matter how fast you were sliding a micro second before.
    • I could add some up force, and only let players move, when they're on the ground, but I foresee this could cause problems with other spell effects and such.

    So I'm looking for some inspiration here. Any ideas?
     
  2. Thiem

    Thiem

    Joined:
    Jun 30, 2014
    Posts:
    20
    So I found a way: I changed line 6 to

    rb.MovePosition(transform.position + moveAmount * Time.fixedDeltaTime);

    And I get the effect I was looking for.
     
  3. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,478
    You should always use "rb.position" and not "transform.position" because when using interpolation or extrapolation the transform and rigidbody poses might be different.
     
    Thiem likes this.
  4. Thiem

    Thiem

    Joined:
    Jun 30, 2014
    Posts:
    20
    Good point. Just the other day my teleport mechanics messed up because the transform had moved, but the rb.position had not been updated. Made a dirty hack to skip a FixedUpdate, so the rb could be updated.