Enemy AI Following Player

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

I’m trying to get an enemy in my game to follow the player, but no matter what I do, nothing is working. Any suggestions?

This question is too generic. Include example(s) of what you’ve tried and maybe someone can help. What kind of nodes are you using for your player and enemy. How do you want it to follow - is this 2D? 3D? Top-down? Side-scroller?

You’ll find that you get better answers when you ask more specific questions. If you’re struggling with very general things, then you should read/watch some tutorials to help get you started. The official docs have some, or you can try some of the Community Tutorials

kidscancode | 2018-07-31 04:10

Here’s my code. Right now I’m only focusing on player 1 getting followed. I’ll add in player 2 and a way to determine which to follow after I get this problem fixed.

extends KinematicBody2D

onready var player = get_node("res://Player.tscn")
onready var player2 = get_node("res://Player2.tscn")
var velocity = Vector2()
var speed = 400

func _process(delta):
	if player.position.x > position.x:
		velocity.x += speed
	if player.position.x < position.x:
		velocity.x -= speed
	if player.position.y > position.y:
		velocity.y += speed
	if player.position.y < position.y:
		velocity.y -= speed
		
func _physics_process(delta):
	velocity = move_and_slide(velocity * delta)

ThreeSpark | 2018-07-31 15:08

Don’t put {} symbols around your code. Use the button above the editor box, just above where you’re typing. It looks like “{}” and it’s between the one that looks like quote marks and the one that looks like a photo.

kidscancode | 2018-07-31 15:12

Yeah I figured that out.

ThreeSpark | 2018-07-31 15:13

:bust_in_silhouette: Reply From: kidscancode

The first problem you have is this:

onready var player = get_node("res://Player.tscn") 
onready var player2 = get_node("res://Player2.tscn")

get_node() requires a node path, not a filename. res://Player.tscn is the file you’ve saved your player scene in.

get_node() needs to know where a node is in the Scene Tree. I don’t know what your tree looks like, so I can’t tell you what to put there.

I answered this exactly in your other question:

For example, if this was your tree:
Main (Node or Node2D)
– Player
– Enemy
Then in the enemy script you can reference the player by using get_node('../Player')

This is all covered in the Documentation. You really should go through the “Step by step” section, it will clear up a lot of this for you.

Ok - I changed the variables to

onready var player = get_node("Node2D/Player")
onready var player2 = get_node("Node2D/Player2"

but there is an error message that says “Invalid get index ‘position’ (on base: ‘null instance’)”
Any solutions? If needed, here is all of my code:

extends KinematicBody2D

onready var player = get_node("Node2D/Player")
onready var player2 = get_node("Node2D/Player2")
var velocity = Vector2()
var speed = 400

func _process(delta):
	if player.position.x > position.x:
		velocity.x += speed
	if player.position.x < position.x:
		velocity.x -= speed
	if player.position.y > position.y:
		velocity.y += speed
	if player.position.y < position.y:
		velocity.y -= speed
		
func _physics_process(delta):
	velocity = move_and_slide(velocity * delta)

ThreeSpark | 2018-08-01 00:40

“Node2D/Player” is not the path of your player relative to the enemy. I even told you in my comment what to put:

get_node('../Player')

Node paths are relative to the calling node. When you put “Node2D/Player” you’re saying “look for a child of the enemy called ‘Node2D’ that has a child named ‘Player’”. However, that’s not where the player is. The player is a sibling of the enemy, so you need to go up one level ".." (which means the parent node) and then you can find Player. Are you familiar with folders on the computer? “…” means parent folder in the same way.

kidscancode | 2018-08-01 00:53

Thank you very much! I thought by “…Player” the “…” meant “what is before”. Thank you for that clarification!

ThreeSpark | 2018-08-01 01:15

I am faced with a new problem. I got my slime to follow my player’s x axis, but for some reason won’t follow the y axis. Here’s my code:

extends KinematicBody2D

onready var player = get_node("../Player")
var velocity = Vector2()
var speed = 5000

func _process(delta):
	if player.position.x > position.x:
		velocity.x += speed
	if player.position.x < position.x:
		velocity.x -= speed
	if player2.position.y > position.y:
		velocity.y += speed
	if player2.position.y < position.y:
		velocity.y -= speed

func _physics_process(delta):
	velocity = move_and_slide(velocity * delta)

Nevermind - realized I was using the wrong variable!

ThreeSpark | 2018-08-01 02:44

New problem - I added states and animations, and for some reason, when the enemy needs to follow the player along the x axis, it gets very glitchy, constantly switching between all of the states. (note: it may be because the enemy is smaller than the player, and if so, how do I fix this without changing the size?) Any solutions? Here’s my code:

extends KinematicBody2D

onready var player = get_node("../Player")
var velocity = Vector2()
var speed = 5000
enum {RIGHT, LEFT, UP, DOWN, IDLE_RIGHT, IDLE_LEFT, IDLE_UP, IDLE_DOWN}
var anim
var new_anim
var state

func change_state(new_state):
	state = new_state
	match state:
		RIGHT:
			new_anim = 'right'
		LEFT:
			new_anim = 'left'
		UP:
			new_anim = 'up'
		DOWN:
			new_anim = 'down'
		IDLE_RIGHT:
			new_anim = 'idle_right'
		IDLE_LEFT:
			new_anim = 'idle_left'
		IDLE_UP:
			new_anim = 'idle_up'
		IDLE_DOWN:
			new_anim = 'idle_down'

func _ready():
	change_state(IDLE_RIGHT)

func _process(delta):
	if player.position.x > position.x:
		velocity.x += speed
		change_state(RIGHT)
	if player.position.x < position.x:
		velocity.x -= speed
		change_state(LEFT)
	if player.position.y > position.y:
		velocity.y += speed
		change_state(DOWN)
	if player.position.y < position.y:
		velocity.y -= speed
		change_state(UP)
	if new_anim != anim:
		anim = new_anim
		$AnimationPlayer.play(anim)

func _physics_process(delta):
	velocity = move_and_slide(velocity * delta)

ThreeSpark | 2018-08-01 03:02

what was the wrong variable?

David000 | 2021-12-30 19:02