Knockback in godot

Godot Version

4.6

Question

Im wondering why knock back wont work when i print the values seems to be fine just not moving player pls recomend any other code changes ik my code is not great

player code:
extends CharacterBody2D


const SPEED = 300.0
const JUMP_VELOCITY = -400.0

@export var minknockback := 100
@export var slowknockback := 1.1

var knockback:Vector2

@onready var sprite_2d: Sprite2D = $Sprite2D
@onready var sprite_2d_2: Sprite2D = $Sprite2D2
@onready var collision_shape_2d_2: CollisionShape2D = $CollisionShape2D2
@onready var sprite_2d_3: Sprite2D = $Sprite2D3
@onready var timer: Timer = $Timer







func _physics_process(delta: float) -> void:

	
	if knockback.length() > minknockback:
		knockback /= slowknockback
		velocity = knockback
		move_and_slide()
		return
	
	
	
	# Add the gravity.
	if not is_on_floor():
		velocity += get_gravity() * delta


	if Input.is_action_just_pressed("plr1_hit"):
		collision_shape_2d_2.disabled = false
		sprite_2d_2.show()
		sprite_2d_3.hide()
		timer.start()
		
		

	# Handle jump.
	if Input.is_action_just_pressed("jump") and is_on_floor():
		velocity.y = JUMP_VELOCITY
	
	
	if not is_on_floor():
		sprite_2d.frame = 1
		
		
	if is_on_floor():
		sprite_2d.frame = 0
		
		
		
	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	var direction := Input.get_axis("left", "right")
	if direction != 0:
		
		
		
		sprite_2d.flip_h=direction >0
		sprite_2d_2.flip_h = direction > 0
		sprite_2d_3.flip_h = direction > 0
		sprite_2d_2.position.x = abs(sprite_2d_2.position.x) * sign(direction)
		sprite_2d_3.position.x = abs(sprite_2d_3.position.x) * sign(direction)
		collision_shape_2d_2.position.x = abs(collision_shape_2d_2.position.x) * sign(direction)
		
	
		velocity.x = direction * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)

	move_and_slide()


func _on_timer_timeout() -> void:
	collision_shape_2d_2.disabled = true
	sprite_2d_2.hide()
	sprite_2d_3.show()


func _on_area_2d_body_entered(body: Node2D) -> void:
	pass # Replace with function body.


knockback for that play code:extends Area2D

@export var knockback := 500

# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	pass # Replace with function body.


# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	pass


func _on_body_entered(body: CharacterBody2D):
	body.knockback = position.direction_to(body.position) * knockback


code for other player:
extends CharacterBody2D


const SPEED = 300.0
const JUMP_VELOCITY = -400.0

@export var minknockback := 100
@export var slowknockback := 1.1

var knockback:Vector2

@onready var sprite_2d: Sprite2D = $Sprite2D
@onready var sprite_2d_2: Sprite2D = $Sprite2D2
@onready var collision_shape_2d_2: CollisionShape2D = $CollisionShape2D2
@onready var hit: Sprite2D = $Hit




@onready var timer: Timer = $Timer





func _physics_process(delta: float) -> void:

	
	if knockback.length() > minknockback:
		knockback /= slowknockback
		velocity = knockback
		move_and_slide()
		return
	
	
	
	# Add the gravity.
	if not is_on_floor():
		velocity += get_gravity() * delta


	if Input.is_action_just_pressed("plr2_hit"):
		collision_shape_2d_2.disabled = false
		hit.show()
		sprite_2d_2.hide()
		timer.start(0.5)
		


	# Handle jump.
	if Input.is_action_just_pressed("ui_up") and is_on_floor():
		velocity.y = JUMP_VELOCITY
	
	
	if not is_on_floor():
		sprite_2d.frame = 1
		
		
	if is_on_floor():
		sprite_2d.frame = 0
		
		
		
	# Get the input direction and handle the movement/deceleration.
	# As good practice, you should replace UI actions with custom gameplay actions.
	var direction := Input.get_axis("ui_left", "ui_right")
	if direction != 0:
		sprite_2d.flip_h=direction >0
		hit.flip_h = direction > 0
		sprite_2d_2.flip_h = direction > 0

		hit.position.x = abs(hit.position.x) * sign(direction)
		sprite_2d_2.position.x = abs(sprite_2d_2.position.x) * sign(direction)
		collision_shape_2d_2.position.x = abs(collision_shape_2d_2.position.x) * sign(direction)
		
		
		
	
		velocity.x = direction * SPEED
	else:
		velocity.x = move_toward(velocity.x, 0, SPEED)

	move_and_slide()


func _on_timer_timeout() -> void:
	collision_shape_2d_2.disabled = true
	sprite_2d_2.show()
	hit.hide()

Do you mind showing where the knockback is set and what are the print values that you get?
With the knockback are you not moving anywhere? Are you moving too far? What does not working mean?

This thread helps walk you through the process of creating a new help topic:

A note that I’m seeing is, with the way that you are handling knockback, unless you’re setting knockback instead of using += (which would let multiple things knock the player around at once) you’re going to have velocity stored between launches because as soon as the knockback is smaller than the minimum, it starts counting down.
If you are just setting velocity, this won’t be an issue, just something to pay attention to.

I don’t know your exact idea for the project, but as long as you have proper acceleration and deceleration set, you can create a function in the player called apply_knockback() and it can take in two parameters. A strength, and an attacker position.
Then in the actual function it would add to the player’s velocity the attacker position’s direction to the player, multiplied by the strength. Then it will launch the player while giving them control as they move.

The actual code for this is as folows:

func apply_knockback(attacker_position : Vector2, strength : float) -> void: # attacker_position must be in global space
    velocity = attacker_position.direction_to(global_position) * strength

I believe you only set velocity to knockback one frame.

Could you add a print where you set it to knockback? Just to see if it happens once or more.

If this is the problem, set some kind of timer to decide how long the knockback should last, or decrease the knockback every frame and cancel it when it gets below minknockback.

The files were not made global so nobody can see them :\

it wouldnt let me do tis the first time cause i was new or sumthin so hopefully this work

These two velocity.x changes will pretty much negate any applied horizontal knockback instantly.

The first change is setting velocity.x directly, so any change to velocity before is overwritten entirely.

The second is using move_toward which is a step in the right direction, but with SPEED as the third argument it will reduce the velocity by the characters max speed every frame (which is very fast)

I’d recommend replacing both lines with move_toward using a per-second delta value, make a new variable for ACCELERATION and set it to be about 4x SPEED or higher.

var direction := Input.get_axis("ui_left", "ui_right")
if direction != 0:
    # etc...
velocity.x = move_toward(velocity.x, direction * SPEED, ACCELERATION * delta)

movements a little slipery now and i dont think that changed much