Hi everyone, I’m implementing knockback in a 2D game in Unity, but I’m having a physics problem where the player and enemies are launched upwards instead of backwards. I’ve already made several changes and checked the animations, I’ve also disabled all movement updates during knockback and increased the force. Does anyone know what the problem might be? Here’s the knockback code and a video showing what’s happening.
using System;
using System.Collections;
using UnityEngine;
namespace Greentale {
public class KnockBack : MonoBehaviour {
[SerializeField] private float _knockbackDuration = 0.25f;
[SerializeField] private float _horizontalForce = 15f;
[SerializeField] private float _verticalPop = 5f;
private float _normalGravityScale;
[Header("Feel")]
[SerializeField] private AnimationCurve _decayCurve = AnimationCurve.EaseInOut(0, 1, 1, 0);
public bool IsBeingKnockedBack {get; private set;}
private Rigidbody2D _rigidBody;
private WaitForFixedUpdate waitFixed;
private Coroutine knockbackCoroutine;
public Action OnKnockbackStart;
public Action OnKnockbackEnd;
private void Awake() {
_rigidBody = GetComponent<Rigidbody2D>();
_normalGravityScale = _rigidBody.gravityScale;
waitFixed = new();
}
public void CallKnockback(Vector2 damageSourcePosition) {
float horizontal = transform.position.x - damageSourcePosition.x;
Vector2 knockDir = new Vector2(Mathf.Sign(horizontal), 0f);
if (knockbackCoroutine != null) {
StopCoroutine(knockbackCoroutine);
}
knockbackCoroutine = StartCoroutine(KnockBackAction(knockDir));
}
public IEnumerator KnockBackAction(Vector2 direction) {
IsBeingKnockedBack = true;
OnKnockbackStart?.Invoke();
_rigidBody.gravityScale = _normalGravityScale;
_rigidBody.velocity = Vector2.zero;
float elapsed = 0f;
float startHorizontalVelocity = direction.x * _horizontalForce;
_rigidBody.velocity = new Vector2(startHorizontalVelocity, _verticalPop);
Debug.Log($"[KNOCKBACK INÍCIO] Velocidade aplicada: {_rigidBody.velocity}");
while (elapsed < _knockbackDuration) {
elapsed += Time.fixedDeltaTime;
float t = elapsed / _knockbackDuration;
float currentHorizontal = startHorizontalVelocity * _decayCurve.Evaluate(t);
_rigidBody.velocity = new Vector2(currentHorizontal, _rigidBody.velocity.y);
Debug.Log($"[KNOCKBACK RODANDO] Tempo: {t:F2} | Vel X Alvo: {currentHorizontal:F2} | Vel X Real do Rigidbody: {_rigidBody.velocity.x:F2}");
yield return waitFixed;
}
_rigidBody.velocity = new Vector2(0f, _rigidBody.velocity.y);
IsBeingKnockedBack = false;
OnKnockbackEnd?.Invoke();
Debug.Log("[KNOCKBACK FIM]");
}
}
}

