Skip to content

Instantly share code, notes, and snippets.

@lazuee
Last active September 30, 2023 09:17
Show Gist options
  • Save lazuee/e61563384248215e2a4d4576eba9eccc to your computer and use it in GitHub Desktop.
Save lazuee/e61563384248215e2a4d4576eba9eccc to your computer and use it in GitHub Desktop.
Godot 4 Beta 1 - Click to Move with NavigationAgent2D
extends Node2D
class_name MovementController
var player : CharacterBody2D = null
func _ready():
var parent = self.get_parent()
if parent:
if parent.get_class() == "CharacterBody2D": player = parent
func _unhandled_input(event):
if event is InputEventMouseButton:
var mouse_event = event as InputEventMouseButton
if mouse_event.is_pressed() and mouse_event.button_index == MOUSE_BUTTON_LEFT:
var target_location = get_global_mouse_position()
player.set_target_position(target_location)
extends CharacterBody2D
class_name Player
signal path_changed(path : PackedVector2Array)
@export_range(1, 5, 1) var walk_speed : float = 3
@export_range(1, 5, 1) var acceleration : float = 3
var _agent : NavigationAgent2D = null
var _velocity := Vector2.ZERO
var _path : PackedVector2Array = []
var _is_finished := false
func _ready():
for child in self.get_children():
if child.get_class() == "NavigationAgent2D":
_agent = child
break
if _agent == null:
_agent = NavigationAgent2D.new()
_agent.name = "NavigationAgent2d"
self.add_child(_agent)
if _agent != null:
_agent.set_target_position(self.position)
_agent.path_changed.connect(_on_path_changed)
_agent.velocity_computed.connect(_on_velocity_computed)
_agent.radius = 35.0
_agent.path_desired_distance = 50.0
_agent.target_desired_distance = 100.0
_agent.path_max_distance = 10.0
_agent.max_speed = (walk_speed * 100) * (acceleration * 0.5)
_agent.avoidance_enabled = true
# Start move when this method called.
func set_target_location(mouse_target: Vector2) -> void:
_agent.set_target_position(mouse_target)
self.set_active(true)
func _physics_process(delta):
if not visible: return
_is_finished = true
var target_global_position = _agent.get_next_path_position()
var direction := Vector2(lerp(self.global_transform.origin, target_global_position, 0.5)).direction_to(target_global_position)
if _path.size() > 1:
if _agent.distance_to_target() > _agent.radius:
var desired_velocity := direction * _agent.max_speed
var steering = (desired_velocity - _velocity) * delta * 4.0
_velocity += steering
_agent.set_velocity(_velocity)
_is_finished = false
if _is_finished:
self.path_changed.emit([])
self.set_active(false)
func _on_velocity_computed(safe_velocity):
velocity = safe_velocity
move_and_slide()
func set_active(enable : bool):
if enable == null or enable:
set_physics_process(true)
else:
_agent.set_target_position(self.global_transform.origin)
set_physics_process(false)
func _on_path_changed():
_path = _agent.get_current_navigation_path()
self.path_changed.emit(_path)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment