Godot Version
v4.2.2.stable.official [15073afe3]
Question
tl;dr: Navigation Path is not computed while in tactical pause
Hi! I’m learning Godot and I’m trying to create a game with party management and tactical pause (DAO like).
In any moment, the player can push a button to pause combat: characters, enemies and props are frozen, but the player can still decide where characters should move (with pathfinding, by clicking on floor) and other things like the next skill to apply.
The problem here is that I want to show navigation path even in combat pause:
- while in combat pause, the player clicks on floor with a character selected
- the new navigation map is computed
- the navigation map is displayed
- the character is still frozen while combat pause is active
To create the combat pause, I set process and physics_process of the characters to false. This for the minimal example, because there are also things like setting Animation Tree’s process mode to Node.PROCESS_MODE_DISABLED to pause animation
The navigation path is not computed while in combat pause, I tried different options, like manually enabling navigation agent’s process/physics_process and pathfinding’s specific component.
What I don’t understand is why the navigation agent’s target is indeed changed even in combat pause but the navigation path is not updated and thus can’t be rendered.
The navigation path is computed immediately after resuming combat, even if the target is chosen while in combat pause.
I recreated a minimal example (that i don’t know how to share here) and the mentioned problem still persists.
The minimal example consists in a plane that act as floor, a character and a camera.
The ReferenceRect is used just to check if we’re in combat pause or not.
Ther are two custom input actions:
- “combat_pause”, set to Spacebar
- “mouse_select”, set to Mouse Left Button
Main script:
extends Node3D
@onready var character: Character = $CharacterBody3D
@onready var camera: Camera = $Camera3D
@onready var pause_rect: ReferenceRect = $ReferenceRect
var is_combat_paused := false:
set(value):
is_combat_paused = value
on_combat_paused_changed(value)
func _input(event: InputEvent) -> void:
if event.is_action_pressed("combat_pause"):
is_combat_paused = not is_combat_paused
pause_rect.visible = is_combat_paused
func _ready() -> void:
camera.target_path_finding_changed.connect(func(value):
character.navigation_agent.target_position = value
)
func on_combat_paused_changed(value: bool):
character.set_process(not value)
character.set_physics_process(not value)
CharacterBody3D script:
class_name Character extends CharacterBody3D
@onready var navigation_agent: NavigationAgent3D = $NavigationAgent3D
const SPEED = 5.0
# Get the gravity from the project settings to be synced with RigidBody nodes.
var gravity: float = ProjectSettings.get_setting("physics/3d/default_gravity")
func _physics_process(delta: float) -> void:
# Add the gravity.
if not is_on_floor():
velocity.y -= gravity * delta
var direction = navigation_agent.get_next_path_position() - global_position
direction = direction.normalized()
velocity.x = move_toward(
velocity.x,
direction.x * 5,
20 * delta
)
velocity.z = move_toward(
velocity.z,
direction.z * 5,
20 * delta
)
move_and_slide()
Camera3D script
class_name Camera extends Camera3D
@export var actor: Character
@onready var ray_cast_3d: RayCast3D = $RayCast3D
signal target_path_finding_changed(value: Vector3)
func update_target_position():
# Pathfinding
var mouse_pos = get_viewport().get_mouse_position()
var ray_length = 100
var from = project_ray_origin(mouse_pos)
var to = from + project_ray_normal(mouse_pos) * ray_length
var space = get_world_3d().direct_space_state
var ray_query = PhysicsRayQueryParameters3D.new()
ray_query.from = from
ray_query.to = to
ray_query.collide_with_areas = true
var raycast_result = space.intersect_ray(ray_query)
if "position" in raycast_result.keys():
if raycast_result["collider"] is StaticBody3D:
target_path_finding_changed.emit(raycast_result["position"])
func _input(event):
if event is InputEventMouseButton:
if event.is_action_pressed("mouse_select"):
update_target_position()