It heavily depends on how you are coding your character movement.
But a general idea would be to have a vector variable that stores the “impulse” and:
when the knockback has to happen set the impulse it to the direction your character has to rebound toward with some magnitude (*);
on each frame:
add it to whatever movement the character would normally do;
damp the impulse, for instance, by multiplying it by some number (*) lower than 1 until it reaches almost zero length, setting it to true zero then.
*: Both the initial magnitude and the damping coefficient may be determined with some test and error.
UPDATE: @eons’ suggestion about using a Tween or an animation is very relevant. I don’t know if that’s what he means, but they may allow you to avoid implementing the damping yourself and instead use a curve from those. You have to consider the tradeoffs, but that’s an option.
Usually, a tween or animation is enough, but these tend to mess up collisions, is possible to do it collision-aware, though.
Using a state machine should help you a lot on isolating the knockback behavior.
here’s my version of knock back system. It can be used in variety of ways in 2d form.
This is were the knockback happends:
var collision = move_and_collide(velocity * delta)
if collision:
var reflect = collision.remainder.bounce(collision.normal)
velocity = velocity.bounce(collision.normal)
reflect = move_and_collide(reflect)
velocity = velocity.move_toward(Vector2.ZERO, 90 * delta)
if velocity == Vector2.ZERO:
states = (It returns back to your previous states after the knock back)
This is the function in were you put the direction on were to knock back:
func knockback(_point_from_knockback : Vector2):
var knock_point = _point_from_knockback - global_position
velocity = -knock_point.normalized() * 80
states = (whatever state knock back is)