How to make enemy chase player 2d platformer

Godot Version

4.2

Question

Hello friends, I’m trying to make a very simple code for which a CharicterBody2D follows the player around on the x-axis in a platformer type game, however no matter what I try I can never seem to get it to work. I’m sure this is an easy fix, but I am new to Godot and the various methods I’ve tried and found online don’t seem to work. My node tree is just the CharicterBody2D as well as a Sprite and CollisonShape as its children, this is my script.

extends CharacterBody2D

@onready var plr = $"."

var movement = Vector2()
var speed = 300
var direction : float


func _physics_process(delta):
	
	move_and_slide()
	
	if !is_on_floor():
		velocity.y += 100
	if velocity.y > 100:
		velocity.y = 100
	
	if plr.position.x > position.x:
		direction = 1
	elif plr.position.x < position.x:
		direction = -1
		
	velocity.x = speed * direction

Thank you for any advice you can offer.

Hm… I’m not entirely clear what it is you are trying to achieve. What you reference as the “player”, is that the Sprite2D?

A few things about your code, plr variable referring to $""." could easily be replaced by self, it would have the same effect, you are referring to the node that this script is attached to. Then you could simply remove self (or plr directly), because plr.position, self.position and position is exactly the same thing - the position of the node the script is attached to. (So plr.position.x > position.x will never return true, as they are the same.)

Secondly, I would move the call to move_and_slide to the very end of _physics_process, since the way you have it now is first you move, then you update velocity (should happen before hand), which isn’t applied until the next frame.

1 Like

What’s currently happening with the player?

Another thing, your “plr” variable seems to refer to “.”, which is essentially saying “self”.

Additionally, position.x is the same as saying self.position.x.

So what you’re currently saying is:

if self.position.x > self.position.x:
     direction = 1
...
// Other directions

As you can see, this will never be true, if you want to get the player, position, then you need a reference to a different node.

I would recommend creating a different Characterbody2d or sprite 2D not parented to this player, whatever you want to follow the player, and then just passing a reference to the player at some point to it:

@onready var player = $"PlayerNode"

Inside of a separate “Enemy” script.

Hopefully that helps clarify some!

1 Like

Player movement is not done correctly, you are comparing the player’s position and the player’s position…
To make your entity move, you need to get movement from the keyboard this can be done as follows
var direction = Input.GetAxis(“left-button”, “right-button”). (or Input.get_axis, I don’t remember exactly).
In this case left-button is a negative action of -1 (if memory serves me correctly), and right-button is +1 for positive action. Thus we have a left and a right direction.
To make it move make a simple code:
Velocity.X = direction * speed (you can also multiply by time, but that’s a separate story).

1 Like

You can also check out the official tutorials, they have enough information to meet your needs for now.

Thank you all for replying! For clarification I did already have another scene that was used for the playable character and their controls, and ‘plr’ was a CharicterBody2D node in the playable character scene. As some noted the issue came from the ‘@onready var’ which I got by ctrl + drag the ‘plr’ node from the main character scene.

Doing the same ctrl + drag from the world scene that contains both (the plr and enemy) CharicterBody2Ds seemed to work, as well as just re-writing the variable to ‘@onready var plr = $“…/plr”’

I figured it was something simple like that, such a minor fix. Sorry for being unclear in my initial post, I think that caused some confusion. Thank you all for helping out a Godot noob!

1 Like