extends CharacterBody3D ## Speed of enemy @export var speed: float = 2.0 ## Target for enemy to follow @export var target: Node3D ## Whether to use gravity on enemy @export var gravity_enabled: bool = true ## Use nav mesh or dumb path finding @export var use_nav_mesh: bool = true @onready var nav_agent: NavigationAgent3D = $NavigationAgent3D var gravity : float = ProjectSettings.get_setting("physics/3d/default_gravity") var original_material: StandardMaterial3D @onready var red_material = preload("res://models/red_material.tres") var mesh_ready = false var found = false func _ready() -> void: if gravity_enabled: motion_mode = MotionMode.MOTION_MODE_GROUNDED NavigationServer3D.connect("map_changed", map_changed) original_material = $MeshInstance3D.get_active_material(0) func map_changed(_rid): print("Map changed") mesh_ready = true func update_target_location(target_location: Vector3): nav_agent.target_position = target_location func chase_nav_mesh(delta: float): if not mesh_ready: return if target != null: update_target_location(target.global_position) var current_location = global_transform.origin var next_location = nav_agent.get_next_path_position() var new_velocity = (next_location - current_location).normalized() * speed #print("Target is ", next_location) # We only want to navigate on XZ plane new_velocity.y = 0 velocity = velocity.move_toward(new_velocity, .25) if not is_on_floor() and gravity_enabled: velocity.y -= gravity * delta else: velocity.y = 0 move_and_slide() func wander() -> void: pass func _physics_process(delta: float) -> void: if Input.is_action_pressed("ui_right"): return if target != null and not found and check_target_visible(): found = true print("Found player") if not found: wander() elif found: chase_nav_mesh(delta) func check_target_visible() -> bool: var space_state = get_world_3d().direct_space_state var starting_pos = global_position var ending_pos = target.global_position + Vector3.UP var query = PhysicsRayQueryParameters3D.create(starting_pos, ending_pos, 0x3, [self.get_rid()]) var result = space_state.intersect_ray(query) print("Checking player") if result: print("Hit ", result.collider, " Target ", target, " Self ", self) if result and result.collider == target: return true return false func on_hit(_hit_position: Vector3) -> void: if $HitTimer.is_stopped(): $MeshInstance3D.set_surface_override_material(0, red_material) $HitTimer.start() func _on_hit_timer_timeout() -> void: $MeshInstance3D.set_surface_override_material(0, original_material) $HitTimer.stop() get_parent().remove_child(self) queue_free() func _on_body_entered(body: Node3D) -> void: target = body func _on_body_exited(body: Node3D) -> void: if body == target and not found: target = null