How do I tell my enemy script where the player is

Godot Version

4.3

Question

` trying to make my enemy to lerp toward the player but without going up but i’ll figure that out later right now im trying to make TARGET_POSISTION to be set to the players position but I cant make it work here is the code:
extends AnimatableBody2D

var MOVE_SPEED = 200
var TARGET_POSISTION = ??

Called every frame. ‘delta’ is the elapsed time since the previous frame.

func _process(delta: float) → void:
$AnimatedSprite2D.play(“idle”)
position = position.lerp(TARGET_POSITION, delta * MOVE_SPEED)

func _on_area_2d_body_entered(body: Node2D) → void:
print(‘ah’)
`

The really ugly solution that shouldn’t be used for anything but demonstration purposes is to directly add the player to your enemy scene:

@export var player : WhateverYourPlayerTypeIs = null # set from inspector

func _process(delta : float)->void:
	# your code here
	if player != null:
		TARGET_POSITION = player.global_position

This is a REALLY BAD solution. More complicated but much neater would be to use something like a ray2D. You can add it to your enemy scene and add a script to the ray2D so that when it detects the player, it gets its position and sends a signal to the main script, so TARGET_POSITION can be set. It’ll take longer to implement, but it won’t break under a stiff breeze.

1 Like

You could use an Area2d as a “vision” area, when the player enters, store their node, or a @export variable for the player node.

# as export you can assign in the Inspector
@export var target_player: CharacterBody2D

# with an Area2D you can store the player dynamically
func _on_vision_body_entered(body: Node2D) -> void:
    if body.name == "Player":
        target_player = body

Use move_toward instead of lerp, the third parameter differs in each, move_toward is pixel-based, lerp is percentage based.

Storing the position will create a copy that doesn’t update as the player moves, so I suspect you want to store the player Node, which can access the position as it updates, via target_player.global_position

1 Like

you can also use this script. this was in a tutorial i followed once and i just kept using it.

var player : CharacterBody3D

func _ready():
	player = get_tree().get_first_node_in_group("player")

the downside is that there can only be one node in the player group and it has to be the player

thanks for reminding me about raycasts but how do I make the lerp() only move along the x access since whenever my player character gets in range the enemy moves towards it but also slightly down into the ground I have no idea why its doing that but how do I make it not do that here is the code

extends AnimatableBody2D
@onready var raycast = $RayCast2D
var MOVE_SPEED = 1

Called every frame. ‘delta’ is the elapsed time since the previous frame.

func _process(delta: float) → void:
var location = raycast.get_collision_point()
print(location)

if raycast.is_colliding():
	position = position.lerp(location, delta * MOVE_SPEED)
$AnimatedSprite2D.play("idle")

Keeping position.xy should do what your looking for
Position.xy = position.xy.lerp(location, delta * movement speed)
This moves it horizontally but it can be edited to make it only move in a straight line by removing the y or the X after the position.

A raycast isn’t going to point toward the player on it’s own. You will need to detect collisions or use an @export variable for this to work. A raycast is useful once you have a solution to finding the player.


Make sure to paste code with proper formatting

yeah I already have that setup but he goes in the ground

Based on your script you do not have player detection set up. It seems like this skeleton will try to move slightly right and down. Your raycast is hitting the skeleton, it doesn’t point towards the player, so it will not hit the player.

it does work it it gets the Collison location then lerps towards that
in this code:
image

doesnt work throws back an error

That gets a collision location from the raycast towards the skeleton, not toward the player. Raycasts are good for checking line of sight once you already know where the enemy and the player are, not before you know this.

You probably want a @export or an Area2D to detect broader collisions than a line, if you do want only to detect a line, then you need to face the raycast away from the skeleton, and filter the raycast.get_collider() like you would in my vision Area2D sample

if raycast.is_colliding():
    var collider: Node2D = raycast.get_collider()
    if collider.name == "Player":
        target_player = collider

If you only want one component you must use the global version of lerp or preferably move_toward

position.x = move_toward(position.x, location.x, delta * MOVE_SPEED)
1 Like

I mean it works but the skeleton goes in the ground which is the problem