Godot version 3.5.1 stable

Something really weird is happening in my code and I'm not sure why.
When I print:
print(nav_agent.is_target_reached())
it prints "true".

When I print:
print(nav_agent.is_target_reachable())
it prints "true".

So I want to move my agent when the target is reachable and the target is not reached, so I used this statement (notice the "!" in front of the is_target_reached):
if (!nav_agent.is_target_reached() and nav_agent.is_target_reachable()):
It evaluates to true and still runs the logic inside the if statement which doesn't make sense to me, since both are true my NOT operator should make it so the if statement evaluates (false and true) and skip to the else statement.

But when I evaluate this expression (just swapped the sides of the conditions):
if (nav_agent.is_target_reachable() and !nav_agent.is_target_reached()):
The result is false as it should be.

I tried putting the !nav_agent.is_target_reached() in parenthesis but it still evaluates as true.

For more context:

func _process(delta):
	 # Nav agent movement
	nav_agent.set_target_location(destination)
	if (nav_agent.is_target_reachable() and !nav_agent.is_target_reached()):
		var next_loc = nav_agent.get_next_location()
		var direction = self.translation.direction_to(next_loc)
		velocity = direction * move_speed
	else:
		velocity = Vector3.ZERO
	
	# apply gravity
	velocity.y -= gravity * delta
	
	# apply all movement
	self.move_and_slide(velocity, Vector3.UP)

The weird thing is, when I do the same inside of print statements, it always outputs correctly:
print(nav_agent.is_target_reached() and nav_agent.is_target_reachable()) # True
print(!nav_agent.is_target_reached() and nav_agent.is_target_reachable()) # False
print(nav_agent.is_target_reachable() and nav_agent.is_target_reached()) # True
print(nav_agent.is_target_reachable() and !nav_agent.is_target_reached()) # False

Does anyone know why this would happen?

Also, does anyone know why my character is slowly sinking in the ground? I read somewhere that we should always apply gravity otherwise we won't get the is_on_floor flag from the kinematicBody but I'm still not getting the flag... Any idea what could be causing this as well? Maybe its related to my current issue.

    Lightsheik Does anyone know why this would happen?

    No. But another thing to try is to store the method results in variables, and use the variables in the print statements and conditional statements.

    var reached: bool = nav_agent.is_target_reached()
    var reachable: bool = nav_agent.is_target_reachable()

    I haven't used NavigationAgent. Is it possible that the reached/reachable states could be changing legitimately in between repeated method calls?

    Which Godot version are you using?

      DaveTheCoder Sorry, should've included that in the post.

      I am using Godot version 3.5.1 Stable.

      Weirdly enough, I tried your suggestion and it still evaluates as true no matter the order:

      nav_agent.set_target_location(destination)
      	var target_reached: bool = nav_agent.is_target_reached()
      	var target_reachable: bool = nav_agent.is_target_reachable()
      	if (!target_reached and target_reachable):
      		var next_loc = nav_agent.get_next_location()
      		var direction = self.translation.direction_to(next_loc)
      		velocity = direction * move_speed
      	else:
      		velocity = Vector3.ZERO

      I tried swapping the 2 but still does the same thing (they both evaluates to true and run the if block). It seems to only work when I reference the methods directly in the if statement...

      And I don't think it could change in between the method calls... And if so I would assume the issue would not be as consistent as it it.

      DaveTheCoder Sorry for the repeated reply but something weird happened lol!

      So I changed back this line:
      if (!nav_agent.is_target_reached() and nav_agent.is_target_reachable()):
      Which before would go through and execute the if block.
      BUT, I left the two var you suggested over the if statement and now it works normally...

      I think you might be right with the method calls changing... This is a weird lol.

      The first thing I notice in the docs is that is_target_reached() is a const function but is_target_reachable() isn't. This means is_target_reachable() makes changes of some kind to the nav agent, but is_target_reached() doesn't.

      Looking through the godot source...
      is_target_reached() just returns the value of a variable called target_reached. Makes sense.
      The only way to set target_reached to false is to set a new target.
      is_target_reachable() does a bit more. It can trigger a full rebuild of the path, and one side effect is it can potentially set target_reached to true.

      In your code:

      nav_agent.set_target_location(destination)
      if (nav_agent.is_target_reachable() and !nav_agent.is_target_reached()):

      The set_target_location() call wipes target_reached to false.
      is_target_reachable() then set target_reached to true if you are on the target
      is_target_reached() is then the correct value when checked.

      But if you had it:

      nav_agent.set_target_location(destination)
      if (!nav_agent.is_target_reached() and nav_agent.is_target_reachable()):

      then:
      target_reached is set to false
      is_target_reached() is now invalid, it's always false even if you are on the target
      is_target_reachable is called last, and sets target_reached to the right value, but it's too late.

      The docs should really list side effects like this, it seems like a common combo query to make.

      Slight correction, target_reached is also set to false if you change the map or nav layers, but that's not involved here.

      But something to be aware of: set_target_location will wipe the current path and cause it to be regenerated when checking if reachable. So if the destination isn't changing but you call set_target_location every frame, that's going to be a performance hit. Only call set_target_location if the destination has changed.
      (Not sure how much of a hit, might not be noticeable, but best to be aware)