Moving a bot after waiting for a for to finish without delay

Godot Version

4

Question

Hello. I have a problem. I’m making a 2D soccer game (bird view) and I’m creating a CPU that calculates how to kick the ball so that it scores a goal. This works by predicting the ball’s position from 0.6, 0.7, 0.8 … 2.0 seconds in the future. So, if the ball is too far away, the CPU won’t move because it detects that he won’t achieve the certain position to kick the ball accurately. That’s why I want to make the CPU move directly to the ball if it detects that he is not able to kick the ball. The problem is that I use a for to calculate the balls position in every time in seconds in the future. If I want to move the CPU directly to the ball when the CPU says that he can’t kick the ball, the CPU won’t move constantly because it waits for the for to finish.
Was my explanation clear? Let me know if more details are needed.

extends RigidBody2D

var functionCallable=true
# Radius of the bot's collision = 24.69
# Radius of the ball's collision = 17.06
var AOPPSWS=111.06275 # Amount Of Pixels Per Second Walk Speed - En un segundo avanza 111.06275
@export var walkSpeed=int()
@export var turboSpeed=int()
@export var hyperTurboSpeed=float() 
@export var turboRemaining=float()
var direction=Vector2()
var velocity=Vector2()
var BTBV #Bot to Ball Vector
@export var MDTT=int() #La distancia máxima entre el bot y la pelota para usar el Turbo-- Max Distance To Turbo
@export var mDTT=int() #La distancia minima entre el bot y la pelota para usar el Turbo-- Min Distance To Turbo
@export var MDTHT=int() #La distancia máxima entre el bot y la pelota para usar el HyperTurbo-- Max Distance To HyperTurbo
@export var player: RigidBody2D
@export var ball: RigidBody2D
var ballFP=Vector2(0,0) # Ball Future Position
@onready var bot_2_ray_cast = $Bot2RayCast
@onready var bot_2_ray_cast_pts = $Bot2RayCastPTS
@export var upCorner: Node2D
@export var downCorner: Node2D
@export var DTBBS=float() #Distance To Ball Before Shot
@export var timePrediction: Array=[
	0.6, 0.7, 0.8, 0.9, 1.0,
	1.1, 1.2, 1.3, 1.4, 1.5,
	1.6, 1.7, 1.8, 1.9, 2.0]

var move=true
#Obtiene la magnitud de un vector dado
func GetMagnitude(vector):
	var distance=sqrt(vector.x**2+vector.y**2)
	return distance
	
#Obtiene el vector normalizado del vector dado
func hypotenuseNormalized(vector):
	var hyp=sqrt(vector.x**2+vector.y**2)
	var vectorNormalized=vector/hyp
	return vectorNormalized
	
func FuturePositionBounce():
	var collisionPoint=ball.ball_ray_cast.get_collision_point()
	var ballVelocityNormalized=hypotenuseNormalized(ball.linear_velocity)
	# Collision Point To Ball Position Magnitude
	var CPTBPM = GetMagnitude(ball.position-collisionPoint)
	# The remaining part of the raycast after the wall
	var magnitudeRemaining=GetMagnitude(ball.ball_ray_cast.target_position)-CPTBPM
	var wallNormal= ball.ball_ray_cast.get_collision_normal()
	var unitVector = GetOpositeUnitVector(ballVelocityNormalized,wallNormal)
	var localballFP=collisionPoint+unitVector*magnitudeRemaining
#	print(localballFP)
	ball.ball_ray_cast.target_position=localballFP-ball.position
	return localballFP
func GetOpositeUnitVector(ballVelocityNormalized,wallNormal):
	if wallNormal.x==1:
		ballVelocityNormalized.x*=-1
		return ballVelocityNormalized
	elif wallNormal.x==-1:
		ballVelocityNormalized.x*=-1
		return ballVelocityNormalized
	elif wallNormal.y==1:
		ballVelocityNormalized.y*=-1
		return ballVelocityNormalized
	elif wallNormal.y==-1:
		ballVelocityNormalized.y*=-1
		return ballVelocityNormalized
func _physics_process(delta):
	bot_2_ray_cast.global_rotation=0
	bot_2_ray_cast_pts.global_rotation=0
	if Input.is_action_just_pressed("ui_focus_next"):
		position=Vector2(893.952,364.697)
		
	if functionCallable==true:
		hitBall()
		functionCallable=false
#	if move==true:
#		if get_parent().get_node("Ball")!=null:
#			BTBV=ball.global_position-global_position
#			# Soluciona que el bot atrape la pelota contra la pared
#			#Si su velocidad es poca (Porque su velocidad es mínima al encerrar a la pelota)
#			if GetMagnitude(linear_velocity)<3.1:
#				#Mientras su distancia contra la pelota no sea mayor a 100 px
#				while GetMagnitude(BTBV)<100:
#					#Se mueve para el lado opuesto con respecto BTBV
#					apply_central_force(-velocity)
#					#Para que no deje de responder se espera un poco
#					await get_tree().create_timer(0.01).timeout
				
	
func hitBall():
	# ballFP= ball future position
		for time in timePrediction:
			ballFP=ball.position+(ball.linear_velocity*time)
			ball.ball_ray_cast.target_position=ballFP-ball.position
			await get_tree().create_timer(0.0000000001).timeout
			if ball.ball_ray_cast.is_colliding():
				if ball.ball_ray_cast.get_collider().is_in_group("Player"):
					break
				elif ball.ball_ray_cast.get_collider().get_parent().name=="WallContainer":
					ballFP=FuturePositionBounce()
					
			# Down Corner To Ball Future Position Vector
			var DCTBFPV=ballFP-downCorner.position
			# Up Coner To Ball Future Position Vector
			var UCTBFPV=ballFP-upCorner.position
			var maxAngleToShot=hypotenuseNormalized(DCTBFPV)
			var minAngleToShot=hypotenuseNormalized(UCTBFPV)
			var randomAngleToShotX=randf_range(minAngleToShot.x,maxAngleToShot.x)
			var randomAngleToShotY=randf_range(minAngleToShot.y,maxAngleToShot.y)
			var randomAngleToShot=Vector2(randomAngleToShotX,randomAngleToShotY)
			var positionToShot=ballFP+randomAngleToShot*DTBBS # Distance To Ball Before Shot
			bot_2_ray_cast.target_position=ballFP-position
			if bot_2_ray_cast.is_colliding():
				if bot_2_ray_cast.get_collider().name!="Ball":
					break
			bot_2_ray_cast_pts.target_position=positionToShot-position
			if bot_2_ray_cast_pts.is_colliding():
				break
			# Se fija si al distancia que puede recorrer el bot en función de time es suficiente para llegar a positionToShot
			if GetMagnitude(positionToShot-position)<AOPPSWS*time*0.76:
				var timer2=2.2
				while positionToShot.distance_to(position)>2:
					var direction=hypotenuseNormalized(positionToShot-position)
					apply_central_force(walkSpeed*direction)
					await get_tree().create_timer(get_physics_process_delta_time()).timeout
					timer2-=get_process_delta_time()
					if timer2<=0:
						break
				linear_velocity=Vector2(0,0)
				position=positionToShot
				var timer1=2.2
				while true:
					if GetMagnitude(ball.position-ballFP)/GetMagnitude(ball.linear_velocity)<=0.5934353098:
						var timer=0.3
						while timer>0:
							apply_central_force(hyperTurboSpeed*hypotenuseNormalized(ballFP-position))
							timer-=get_physics_process_delta_time()
							await get_tree().create_timer(get_physics_process_delta_time()).timeout
#						apply_central_impulse(walkSpeed*hypotenuseNormalized(ballFP-position))
						break
					await get_tree().create_timer(0.00001).timeout
					timer1-=get_process_delta_time()
					if timer1<=0:
						break
				break
		functionCallable=true

That’s all my code but the important thing is the function hitBall(). If after time=2 the bot says that it can’t kick the ball, I want to move the bot directly to the ball’s position but if I do that it happens that the bot moves in intervals.