Godot Version
4.4 i think
Question
`Could anyone help me find the error or have a solution on what i did wrong?
The Code i wrote( its probably not optimal since im new to game dev):
extends CharacterBody2D
var speed = 40
var direction = Vector2( 1, 0)
var pursue_player = false
var player = null
@onready var animated_sprite_2d: AnimatedSprite2D = %AnimatedSprite2D
@onready var collision_shape_2d: CollisionShape2D = $DetectionArea/CollisionShape2D
@onready var ray_cast_stick_to_ground: RayCast2D = $Location/RayCastStickToGround
@onready var ray_cast_floor_right: RayCast2D = $Location/RayCastFloorRight
@onready var ray_cast_wall_right: RayCast2D = $Location/RayCastWallRight
@onready var ray_cast_floor_left: RayCast2D = $Location/RayCastFloorLeft
@onready var ray_cast_wall_left: RayCast2D = $“Location/RayCastWall Left”
func _ready():
direction = Vector2( 1, 0)
pursue_player = false
func _physics_process(delta):
if ray_cast_stick_to_ground.is_colliding():
position.y = ray_cast_stick_to_ground.get_collision_point().y
if pursue_player:
direction = (player.position - position).normalized()
velocity = direction * speed
$AnimatedSprite2D.play("walk")
if (player.position.x - position.x) < 0:
$AnimatedSprite2D.flip_h = true
else:
$AnimatedSprite2D.flip_h = false
else:
velocity = direction * speed
$AnimatedSprite2D.play("walk")
if not ray_cast_floor_right.is_colliding() or ray_cast_wall_right.is_colliding():
direction = Vector2( -1 , 0) #Flip the movement direction
if not ray_cast_floor_left.is_colliding() or ray_cast_wall_left.is_colliding():
direction = Vector2( 1 , 0) #Flip the movement direction
if not direction.x == 0:
if direction.x < 0:
$AnimatedSprite2D.flip_h = true
if direction.x > 0:
$AnimatedSprite2D.flip_h = false
move_and_slide()
func _on_detection_area_body_entered(body):
player = body
pursue_player = true
func _on_detection_area_body_exited(body):
player = null
pursue_player = false
It’s a bit difficult for me to follow the code since it’s not under the right tag, but the first advice I’d give you is to augment the speed. 40 is pretty small, I’d go with 400 to make sure there’s REALLY something moving. Not sure how fast 40 is, but it’s low.
// Code uses Preformatted Text (ctrl-e) tag to colorize
for each text:
do:
something()
The quotation marks should not be there ASAIK. This won’t break anything, but still.
There’s also this problem:
which is referred to as:
These might bring some unwanted results. I honestly don’t know if those could be interchanged, but I’d say not.
Hopefully these can help some.
Is 40 small if you don’t use delta? Wouldn’t that end up being 40 * 60 pixels a frame, so 2400 pixels?
Have you debugged using print statements?
Use print(velocity) before and after your two velocity changs, see if they are running and changing.
For my arrows I use this and they’re flying at a convenient speed. You can follow them easily with your eyes.
Also, you should use delta in most cases.
@export var speed:= 800.0
func _physics_process(delta):
position += transform.x * speed * delta
I could try that but we kinda already know that the movement applied by the Velocity doesent applie and 40 as a Speed is fine. If it helps when i walk into the area 2d and start persue_player after that even If i leave everything works totally fine, just the Initial movement at the Launch of the Game (probably in the else part after If pusue_player) doesent start
Yes, so before you do anything it seems the velocity is not being set (potentially). Have you put a print statement in your two conditional statements that control velocity change to see if they are playing at start?
I don’t get how you can say that the speed “is fine” when your post literally says that it’s not moving…
Help me understand.
Also, do you start inside detection area? What is pursue player and player giving you at start? Do exit and enter run right when you load up game? These are all things that you could use print statements to debug to try and find areas to investigate.
It is moving when i start movement by activating persue_player and after that IT moves totally fine but i want it to start moving on its own when starting the scene and currently it just stands still until i “activate it” by Entering the pursue_player area2d
Yes i already used Print for all exits or enters and everything in the persue Player funktion works fine. And no i dont start in the detection area but still thanks for the suggestions 
All i really need is a way to apply the movement when starting the game so if u see any potential ways to implement that at the beginning or so of the function tree the rest will work totally fine
That is where I am confused. Your else statement should run at start setting velocity and move_and_slide should then move the enemy.
Does the else side of your if/else run at start up and at the end of its run what is your velocity?
no the problem is it sort of doesent run so the enemy gets no velocity and doesent move but i dont know why it doesent run, since it does work after i walk into the radius
Try reversing the if/else statement. Make if not pursue_player: then put the code you currently have in else under that and vise versa. I don’t know why at start that part of code isn’t running.
Unless you setting position.y at beginning is messing with something, is that part of the code running at start?
If you get rid of everything else you have using # before it, and just place if pursue_player: velocity = Vector2(1,0) * 40, else: velocity = Vector2(-1,0) * 40, just to see if it works?
Here you go, I made a minimalist recreation of what I figured your setup was. Not knowing how you have everything else set up I had to guess.
This has two characters (enemy, player) and an area2d that detects when player enters.
At start enemy moves away from player, once player enters area2d enemy moves towards player, and once he leaves resumes moving away.
extends CharacterBody2D
const SPEED = 40
var pursue_player: bool = false
var player: Object = null
func _physics_process(delta: float) -> void:
var direction: = Vector2.ZERO
if pursue_player:
direction = (player.position - position).normalized()
else:
direction = Vector2(-1,0)
velocity = direction * SPEED
move_and_slide()
func body_entered(body):
if body is Player2:
player = body
pursue_player = true
func body_exited(body):
if body is Player2:
pursue_player = false
player = null
So, I am not sure if it is in your code that it is broken, or in your node structure, or maybe some of your other extra code. I would start minimalist like I just demonstrated and see if it works, then build up your other functionality until you break it. Then you know that what you just added is the issue.
Honestly you could simplify that more by putting velocity outside the if/else just before move_and_slide()
*** Wait you don’t set direction in your else statement until after your velocity. You should try moving your velocity like I suggested just before move_and_slide() see if that fixes it.
Here is some tweaking
if pursue_player:
direction = (player.position - position).normalized()
else:
if not ray_f_right.is_colliding() or ray_w_right.is_colliding():
direction = Vector2( -1 , 0) #Flip the movement direction
if not ray_f_left.is_colliding() or ray_w_left.is_colliding():
direction = Vector2( 1 , 0) #Flip the movement direction
if direction.x < 0:
animator.flip_h = true
elif direction.x > 0:
animator.flip_h = false
animator.play("walk")
velocity = direction * speed
move_and_slide()
Also, your var are as long as writing out everything, why do you need ray_cast_floor_left? You could do ray_floor_left or ray_left_f. Also ray_left_wall or ray_left_w. For $AnimatedSprite2D you could use animate. Var should be easier to use, simple but communicative.
Also this
if ray_cast_stick_to_ground.is_colliding():
position.y = ray_cast_stick_to_ground.get_collision_point().y
Is unnecessary if you implement a gravity system, set the y velocity = to your gravity force, your character should always cling to floor without needing those extra rays.
You need a reference to the player to track it. If you don’t have that reference, any attempt to track the player will fail, as there’s no target destination. You’re currently only getting that reference when the player enters the area, and you’re setting it back to null when they leave. Rather than feed that reference in every time they enter the area, just export your player
variable from that script and drag in the player node so your enemy can get that location whenever it needs it. Now to make it track from the start, persue_player
should be set to true in your _ready()
function, and it should just work, provided your pathfinding is functional, which it sounds like it is.
In your area detection functions, you should remove any attempt to edit that player node, and just toggle persue_player
on and off as you wish. There should also be some type checking to make sure the body entering is indeed that of the player (to avoid random non-player objects entering and turning on/off persue_player
).