2025-04-21 13:03:19 +01:00
|
|
|
extends RigidBody3D
|
|
|
|
class_name Unit
|
|
|
|
|
|
|
|
@export var movement_force: float = 100
|
|
|
|
@export var max_speed: float = 100
|
2025-04-21 20:49:48 +01:00
|
|
|
@export var minimum_progress_rate: float = 1.0
|
|
|
|
@export var stuck_time: float = 1.0
|
2025-04-21 13:03:19 +01:00
|
|
|
|
|
|
|
var target_velocity: Vector3 = Vector3()
|
2025-04-21 20:49:48 +01:00
|
|
|
var last_distance_to_target: float = 0.0
|
|
|
|
var stuck_timer: float = 0.0
|
2025-04-21 13:03:19 +01:00
|
|
|
|
|
|
|
func _ready() -> void:
|
2025-04-21 20:49:48 +01:00
|
|
|
#$NavigationAgent3D.connect("velocity_computed", avoidance_velocity_computed)
|
|
|
|
pass
|
2025-04-21 13:03:19 +01:00
|
|
|
|
|
|
|
func avoidance_velocity_computed(velocity: Vector3) -> void:
|
|
|
|
if velocity != target_velocity:
|
2025-04-21 20:49:48 +01:00
|
|
|
#DebugDraw3D.draw_line(global_position, global_position + velocity, Color.ORANGE)
|
2025-04-21 13:03:19 +01:00
|
|
|
#print("Avoidance issued!")
|
|
|
|
target_velocity = velocity
|
|
|
|
|
|
|
|
func _process(delta: float) -> void:
|
2025-04-21 20:49:48 +01:00
|
|
|
if $NavigationAgent3D.is_target_reached() \
|
|
|
|
or $NavigationAgent3D.target_position.is_zero_approx() \
|
|
|
|
or !$NavigationAgent3D.is_target_reachable():
|
2025-04-21 13:03:19 +01:00
|
|
|
$NavigationAgent3D.target_position = NavigationServer3D.map_get_random_point(NavigationServer3D.get_maps()[0], 1, true)
|
2025-04-21 20:49:48 +01:00
|
|
|
last_distance_to_target = $NavigationAgent3D.distance_to_target()
|
2025-04-21 13:03:19 +01:00
|
|
|
else:
|
2025-04-21 20:49:48 +01:00
|
|
|
var distance_to_target: float = $NavigationAgent3D.distance_to_target()
|
|
|
|
var progress_rate: float = (last_distance_to_target - distance_to_target) / delta
|
|
|
|
$Label3D.text = "Prog: %f" % progress_rate
|
|
|
|
last_distance_to_target = distance_to_target
|
|
|
|
if progress_rate < minimum_progress_rate:
|
|
|
|
$Label3D.modulate = Color.RED
|
|
|
|
stuck_timer += delta
|
|
|
|
if stuck_timer >= stuck_time:
|
|
|
|
unstuck()
|
|
|
|
else:
|
|
|
|
$Label3D.modulate = Color.WHITE
|
|
|
|
stuck_timer = 0
|
|
|
|
DebugDraw3D.draw_sphere($NavigationAgent3D.target_position, 0.5, Color.RED)
|
2025-04-21 13:03:19 +01:00
|
|
|
var next_point: Vector3 = $NavigationAgent3D.get_next_path_position()
|
|
|
|
DebugDraw3D.draw_sphere(next_point, 0.1, Color.YELLOW)
|
|
|
|
var direction: Vector3 = (next_point - global_position).normalized()
|
|
|
|
#DebugDraw3D.draw_line(global_position, global_position + linear_velocity, Color.BLUE)
|
2025-04-21 20:49:48 +01:00
|
|
|
target_velocity= direction * max_speed
|
|
|
|
#$NavigationAgent3D.velocity = target_velocity
|
|
|
|
#DebugDraw3D.draw_line(global_position, global_position + target_velocity, Color.MAGENTA)
|
|
|
|
#DebugDraw3D.draw_text(global_position + Vector3(0,1,0), "%f" % $NavigationAgent3D.distance_to_target())
|
2025-04-21 13:03:19 +01:00
|
|
|
|
2025-04-21 20:49:48 +01:00
|
|
|
func unstuck() -> void:
|
|
|
|
# teleport to next path point
|
|
|
|
global_position = $NavigationAgent3D.get_next_path_position()
|
|
|
|
stuck_timer = 0
|
2025-04-21 13:03:19 +01:00
|
|
|
|
|
|
|
func _physics_process(delta: float) -> void:
|
|
|
|
if $ShapeCast3D.is_colliding():
|
|
|
|
var force_direction: Vector3 = (target_velocity-linear_velocity)
|
|
|
|
var normal: Vector3 = $ShapeCast3D.get_collision_normal(0)
|
2025-04-21 20:49:48 +01:00
|
|
|
#DebugDraw3D.draw_line(global_position, global_position + normal, Color.DODGER_BLUE)
|
2025-04-21 13:03:19 +01:00
|
|
|
var force: Vector3 = (force_direction * movement_force).slide(normal)
|
2025-04-21 20:49:48 +01:00
|
|
|
#DebugDraw3D.draw_line(global_position, global_position + force, Color.GREEN)
|
2025-04-21 13:03:19 +01:00
|
|
|
apply_central_force(force)
|