Timers not working

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

So, the timer just doesn’t seem to work no matter what I do. First, I am using the timer as a way to control NPC’s, as a way to manipulate movement. Every time the timer times out what is supposed to happen is a specific variable is supposed to increase by an increment of 1, and depening on the values, a direction for the npc is chosen. Basically:

func _ready():
$Timer.start()
var a = 1
$Enemy.velocity.x += 1
pass

func _on_Timer_timeout():
     if (a == 4):
	     a = 1;
     else:
	     a = a + 1;
     $Timer.start()
pass

func velocity_manipulation():
if (a == 1) :
	$Enemy.velocity.x = 0;
	$Enemy.velocity.y += 1;
elif (a  == 2) :
	$Enemy.velocity.y = 0;
	$Enemy.velocty.x -= 1
elif (a == 3) :
	$Enemy.velocity.x = 0;
	$Enemy.velocity.y -= 1
else :
	$Enemy.velocity.x += 1
	$Enemy.velocity.y = 0
pass

With velocity_manipulation() called each frame. The enemy moves, so I know this works.
The problem is the timer doesn’t. I’ve tried everything. I’ve put the timer as a child of the NPC, a child of the main map, I’ve set it to autostart to true in the editor, and I’ve tried manually starting it in the code. I wrote a timeout function in the script of the NPC and in the script of the main map, but nothing works, and at this point I’m genuinely frustrated. It shouldn’t be this hard to make an enemy move in a square. Honestly. Help?

If possible I’d like to make the timer as a child of the specific NPC so that I won’t need multiple timers and bits of code for each one I want to add to the main scene but at this point I’m desperate.

EDIT: I printed time left, and I think what’s happening is that it’s just skipping the timout and restarting. How do I fix that ?

Hi, i know you probably checked this thouthands of times… but are you sure you connected the timeout signal to the _on_Timer_timeout() function?

I’ve used this technique a lot of times and never had this trouble.

May be you can share us the code, and i can see if i can fix it.

p7f | 2019-02-27 22:07

Yeah, I have connected it and still don’t know why it’s working. Right now the configuration I’m using is creating the timer directly in the code:

extends KinematicBody2D

export (int) var speed = 400
var velocity = Vector2()
var x;
var timer
var wait
func _ready():
   x = 0;
   wait = 3
   velocity.x = 0;
   velocity.y = 0;
   timer = Timer.new()
   timer.set_one_shot(true)
   timer.set_wait_time(wait)
   timer.connect("timeout", self, "_on_timeout")
   timer.set_timer_process_mode(0)
   timer.start()
pass

func _on_timeout():
    print("timeout")
    pass

func _move():
if (x == 1): 
	velocity.x = 0
	velocity.y += 1
elif (x == 2):
	velocity.y = 0;
	velocity.x -= 1;
elif (x == 3):
	velocity.x = 0;
	velocity.y -= 1
else:
	velocity.x += 1
	velocity.y = 0
pass

func _process(delta):
_move();
if (timer.is_stopped()):
	x = x + 1
	if (x == 5):
		x = 1;
	print("timout")
	timer.start()
velocity = velocity.normalized() * speed
print(timer.time_left)
pass

And I’ve also tried connecting it with an object created in the editor.

Honestly, some example code might be useful, too.

P.S. there is some extraneous code here as well, just to try and find the issue.

Kayd | 2019-02-28 17:27

Just wanted to make this comment about the structure of the velocity_manipulation() function: have you tried using a match statement to simplify that?

Ertain | 2019-02-28 21:22

:bust_in_silhouette: Reply From: Kayd

Nevermind, this has been resolved. Don’t know how but it works.

Just for people with the same issue : created a timer that was child of the object in the main scene (as opposed to in the NPC scene itself), and then connected it, set one shot to off and autostart to on. Don’t know why it didn’t work before but hope this helps.

Looks like the timer must be a child of the root in order to be startable. Make sure to add the child before starting it.

alantam | 2020-05-29 03:42