Enemy stop following player and I do not understand why

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By DeadLy38

Hi,
I made a script where the enemy has a field of vision and if it sees the player, it will follow and rotate towards him.

But the enemy object just stops midway and only moves again when the player moves.
I also noticed that this happens when the enemy object moves in a straight line towards the player.

I checked every if statement and the other variables, but I just can not figure it out.

This is the code I wrote (It is in the enemy object):

    extends KinematicBody2D

var speed = 50
var FOV = 45
var detection_radius = 400
var velocity = Vector2()

func _physics_process(delta):
	var facing = Vector2(1,0).rotated(rotation).normalized()
	var player = get_parent().get_node("Player")
	var distance_to_player = player.global_position - global_position
	if distance_to_player.length() <= detection_radius:
		if rad2deg(acos(distance_to_player.normalized().dot(facing))) < FOV:
				var direction = (player.global_position - global_position).normalized()
				velocity = direction * speed
				move_and_slide(velocity)
				velocity = move_and_slide(velocity)
				look_at(player.global_position)
:bust_in_silhouette: Reply From: whiteshampoo

This might be a Godot-Bug… (EDIT: Probably more a problem with floating-point-precision-stuff. normalize can’t provide infinite-precise vectors.)

distance_to_player.normalized().dot(facing)

gives values > 1. (Something like 1.0000001)
acos does really NOT like values > 1

Try this:

extends KinematicBody2D

export (float, 1.0, 100.0, 1.0) var speed : float = 50.0
export (float, 0.0, 360.0, 1.0) var FOV : float = 45.0
export (float, 0.0, 1000.0, 5.0) var detection_radius : float = 400.0

var velocity : Vector2 = Vector2.ZERO

onready var player : KinematicBody2D = $"../Player"

func _ready() -> void:
	FOV = acos(deg2rad(FOV))

func _physics_process(delta : float) -> void:
	var facing : Vector2 = Vector2.RIGHT.rotated(rotation).normalized()
	var distance_to_player : Vector2 = player.global_position - global_position
	var direction : Vector2 = distance_to_player.normalized()
	
	if distance_to_player.length() <= detection_radius:
		if direction.normalized().dot(facing) > FOV:
				velocity = direction * speed
				velocity = move_and_slide(velocity)
				look_at(player.global_position)

i optimized a little bit. Please ask, if something is unclear!

EDIT2:
You can debug suchs problems easily, if you just print out some variables while running your game.

Thank you very much for your answer. I will try it out.

I did print the variables and if statements while debugging, but the problem was that there was nothing out of the ordinary visible. Though I did notice that once the dot product reached 0 the enemy just stopped.

Thanks again for your answer, I will come back once I tried it out.

EDIT:
It works now! Thank you very much, I had been struggling with this problem for over a day now!

Just one more question, in your example code you used something called void (like: “func _physics_process(delta : float) → void:”) what does this do exactly?

DeadLy38 | 2020-05-27 09:17

That says the editor, that delta is a float, and the function/method will return nothing (void)

See Static-Typing in the docs.

Use this whenever possible. This can prevent some nasty bugs and helps the editor to help you with autocomplete-suggestions.

whiteshampoo | 2020-05-27 09:34

Hi,

Just wanted to say thank you for your help.
I understand much more about GDscript because of your help :D.

Have a nice day!

DeadLy38 | 2020-05-27 15:19

Always with pleasure :smiley:

(more very handy stuff)

whiteshampoo | 2020-05-27 15:29