0 votes

I have been following this tutorial on how to use Navigation2D because it seems to be exactly what I need, due to the updating path function. In my game, the position that the nodes are moving toward is the player.
Problem
My Enemy node navigates and moves around walls but only moves toward the position where the Player started. I have tried using the pos_update signal to update the path, but that isn't working. It would be very appreciated if someone would help me or introduce me to new methods. (calling update_path() on process() doesn't work)
Main scene code

extends Node2D

signal pos_update

var enem = preload("res://Enemy.tscn")
onready var pos1 = $Position2D.position
onready var pos2 = $Position2D2.position
onready var pos3 = $Position2D3.position
onready var navv = $Navigation2D
onready var end_pos = $Player/Position2D.position



# Called when the node enters the scene tree for the first time.
func _ready():
    pass



# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
#   pass


func _on_Timer_timeout():
    var e = enem.instance()
    add_child(e)
    e.position = pos1
    e.goal = end_pos
    e.nav = navv
    connect("pos_update", e,"update_path")

func _on_Timer2_timeout():
    var e = enem.instance()
    add_child(e)
    e.position = pos2
    e.goal = end_pos
    e.nav = navv
    connect("pos_update", e,"update_path")


func _on_Timer3_timeout():
    var e = enem.instance()
    add_child(e)
    e.position = pos3
    e.goal = end_pos
    e.nav = navv
    connect("pos_update", e,"update_path")

Enemy code

extends KinematicBody2D


const GRAVITY = 950
const WALK_SPEED = 400
onready var player = get_parent().get_node("Player")
var velocity = Vector2()

var DIRECTION_RIGHT = 1
var DIRECTION_LEFT = -1
var direction = Vector2(DIRECTION_RIGHT, 1)
var react_time = 400
var dir = 0
var next_dir_time = 0
var next_dir = 0
var next_dir_y = 0
var next_dir_time_y = 0
var dir_y = 0
var helth = 6
var cn = true


var nav = null setget set_nav
var path = []
var goal = Vector2()

func _ready():
    pass

func set_nav(new_nav):
    nav = new_nav
    update_path()

func update_path():
    path = nav.get_simple_path(position, goal, false)


func _process(delta):
    if path.size() > 1:
        var d = position.distance_to(path[0])
        if d > 2:
            position = position.linear_interpolate(path[0], (WALK_SPEED * delta)/d)
        else:
            path.remove(0)
in Engine by (14 points)
edited by

call "update_path()" on _process()

extends KinematicBody2D


const GRAVITY = 950
const WALK_SPEED = 400
onready var player = get_parent().get_node("Player")
var velocity = Vector2()

var DIRECTION_RIGHT = 1
var DIRECTION_LEFT = -1
var direction = Vector2(DIRECTION_RIGHT, 1)
var react_time = 400
var dir = 0
var next_dir_time = 0
var next_dir = 0
var next_dir_y = 0
var next_dir_time_y = 0
var dir_y = 0
var helth = 6
var cn = true


var nav = null setget set_nav
var path = []
var goal = Vector2()

func _ready():
    pass

func set_nav(new_nav):
    nav = new_nav
    update_path()

func update_path():
    path = nav.get_simple_path(position, goal, false)


func _process(delta):
    update_path():
    if path.size() > 1:
        var d = position.distance_to(path[0])
        if d > 2:
            position = position.linear_interpolate(path[0], (WALK_SPEED * delta)/d)
        else:
            path.remove(0)

I have already tried this. The enemy just spawns and doesn't move.

oh. i guess i tried :/

1 Answer

0 votes

I've done something similar for a sentry enemy that chases players that it sees. From what I can see, the main problem is that the enemies aren't keeping track of the player.

onready var end_pos = $Player/Position2D.position

Instead you should do:

onready var player = $Player/Position2D

...

func _on_Timer2_timeout():
    var e = enem.instance()
    add_child(e)
    e.position = pos2
    e.kinematic_goal = player
    e.nav = navv
    connect("pos_update", e,"update_path")

And then in the enemy:

func update_path():
    path = nav.get_simple_path(position, kinematic_goal.position, false) # Note use of kinematic_goal node to get up-to-date position of player

func _process(delta):
    if path.size() > 1:
        var d = position.distance_to(path[0])
    if d > 2:
        position = position.linear_interpolate(path[0], (WALK_SPEED * delta)/d)
    else:
        path.remove(0)
        update_path() # IMPORTANT BIT

Technically, you could just call updatepath() only when path.size == 0, but I've found that it makes the enemies feel more responsive when they recalculate their direction more consistently (you could also add a counter to updatepath every couple of frames).

by (158 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.