Godot Version
4.6 stable
Question
The idea for this enemy is that every time it hits a wall or is about to fall into the void
(which it detects using ray_down / my raycast), it should change direction. However, my enemy isn’t moving at all.
And my timer is set to 1sec.
extends CharacterBody2D
@export var move_speed : int = 60
var gravity: int = ProjectSettings.get_setting("physics/2d/default_gravity")
var direction: int = -1
var last_direction = -1
@onready var animated_sprite: AnimatedSprite2D = $AnimatedSprite2D
@onready var ray_down: RayCast2D = $RayCastDown
@onready var timer: Timer = $Timer
func _physics_process(delta: float) -> void:
if not is_on_floor():
velocity.y += gravity * delta
if ray_down.is_colliding() == false or is_on_wall():
last_direction = direction
direction = 0
timer.start()
velocity.x = direction * move_speed
move_and_slide()
func _on_timer_timeout() -> void:
if last_direction == -1:
print("go right")
else:
print("go left")
I dont get the print massages.
PS. Is this pice of Sh** any clean?
Update: It now gets stuck on walls and cliffs. Please help!
extends CharacterBody2D
@export var move_speed : int = 60
var gravity: int = ProjectSettings.get_setting("physics/2d/default_gravity")
var direction: int = -1
var last_direction: int = -1
@onready var animated_sprite: AnimatedSprite2D = $AnimatedSprite2D
@onready var ray_down: RayCast2D = $RayCastDown
@onready var timer: Timer = $Timer
func _physics_process(delta: float) -> void:
if not is_on_floor():
velocity.y += gravity * delta
if ray_down.is_colliding() == false or is_on_wall():
print ("new directinon")
last_direction = direction
direction = 0
timer.start()
velocity.x = direction * move_speed
move_and_slide()
func _on_timer_timeout() -> void:
if last_direction == -1:
direction = 1
else:
direction = -1
And it prints new direction every frame.
It has something to do with the wall/cliff detecting collision every frame
See the documentation on what timer.start() does (it resets the timer.)
If your character touches a wall, direction is set to zero and the timer is reset. Therefore, _on_timer_timeout is never called again, and direction never changes (i.e. the character remains in place.)
What is the solution tho this?
Where did you get this code from? Having a gravity variable is from like 3.x
Did you connect the timer’s signal to _on_timer_timeout()?
I coded this myself (without AI/LLMs), and I copied the gravity variable from my player script.
What’s wrong with using a gravity variable? Is there a better solution?
Thank you for taking a look at this!
And sorry, English is not my native language.
It depends on your exact requirements. Personally, I wouldn’t include a timer at all and simply reverse direction whenever the character hits a wall. But that assumes the timer doesn’t serve a purpose, which I can’t know for sure.
The default CharacterBody2D script for 4.6.3 does not have that. This is the default script provided in the editor:
extends CharacterBody2D
const SPEED = 300.0
const JUMP_VELOCITY = -400.0
func _physics_process(delta: float) -> void:
# Add the gravity.
if not is_on_floor():
velocity += get_gravity() * delta
# Handle jump.
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
velocity.y = JUMP_VELOCITY
# Get the input direction and handle the movement/deceleration.
# As good practice, you should replace UI actions with custom gameplay actions.
var direction := Input.get_axis("ui_left", "ui_right")
if direction:
velocity.x = direction * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
move_and_slide()
So I don’t know where your CharacterBody2D script came from, but it’s old.
Yes, using get_gravity(). You can use the variable, but then any gravity changes you make in an Area2D will be ignored.
That’s fine. But you didn’t answer my question.
Yes, the signal connection is fine.
I will update my gravity now, thanks.
The problem now is that I can’t get the delay between each direction change to work.
I want my player to hit a wall, wait 0.5 seconds, and then change direction. Right now it gets stuck because the timer is started every frame. I haven’t been able to find a solution for this yet.
Thanks in advice! 
That’s an easy fix. Replace this:
timer.start()
With this:
if timer.is_stopped():
timer.start()
Thanks man i do realy apriciate the time end efford you put in to this comunety!
And in my dumb posts ( -:
No problem. If one of those posts solved your problem, please mark it as the solution.