Hello! I'm making my first, very basic game. I started using Godot just yesterday, so, sorry if this is a stupid question 😅
I have (hopefully) attached a picture of the problem.

So, the last statement should only happen if 'seconds' is negative, which works the first time, but then suddenly it accepts positive numbers for a short while, e.g. 1.82 has 'entered' the statement, 1.95, 1.88 and so on.

I may just be overlooking something obvious, but for now I'm confused. I feel like that just shouldn't be possible, given the 'seconds < 0'

A little more elaboration:

I hope the gif above works. Basically the character move as intended first time, but then for a few seconds moves in all sort of directions. This, I believe, is because the last if-statement is run multiple times, making the first statement run multiple times as 'seconds' is reset to 2. But maybe that isn't even the case??

Thank you! 🙂

  • Just to give you a better answer, await breaks the normal flow of code. People think it's like a timer or pause, which it can be, but it's asynchronous and if you are not well versed in asynchronous and parallel programming most likely it's gonna crash your app.

Never await inside _process()

    Just never use await. I wish it wasn't even in the language.

    • xyz replied to this.

      Just to give you a better answer, await breaks the normal flow of code. People think it's like a timer or pause, which it can be, but it's asynchronous and if you are not well versed in asynchronous and parallel programming most likely it's gonna crash your app.

      cybereality I wish it wasn't even in the language.

      I'd keep it... but with "here be dragons" stickers slapped all over it 🙂

      I generally don't like things that break the flow of code. I consider await on the same level as GOTO. I would much rather use signals and event driven programming, which can achieve the same goal.

      A mutex doesn't break the flow. It just stops execution, which is probably what people think await is.

      • xyz replied to this.

        cybereality It does stop the execution, but only in the current frame when used in _process(). People who are new to game programming typically don't understand how the main loop works and that the _process() is called perpetually as a part of it. So if you stop the execution in this frame, the new "instance" of the same code will start running immediately in the next frame. The execution eventually needs to return to each of accumulated stopped processes, retrieving the local objects state from before who knows how many seconds. This is quite hard to "visualize" for anyone who hasn't had some previous experience with concurrent code.

        await is quite nice to have for generator coroutines. You can just run an infinite loop and spit out the output from time to time. I wouldn't like a powerful language feature gone just because newcomers tend to misuse it.

        I guess so. I mean, await is useful for networking code in particular. But for single player I haven't needed it yet.

        • xyz replied to this.

          cybereality Coroutines are very useful in realtime apps in general, games especially. For example for doing things like this:

          func fuse():
          	for i in range(10, 0, -1):
          		print(i)
          		await get_tree().create_timer(1).timeout
          	print("BOOM!")
          	
          func _ready():
          	fuse()

          Or streaming data elegantly:

          signal need_next_chunk
          
          func stream_content():
          	var i = 0
          	while true:
          		print("getting_chunk ", i)
          		await need_next_chunk
          		i += 1
          	
          func _ready():
          	stream_content()
          
          func _process(delta):
          	while chunks.size() < chunks_wanted:
          		emit_signal("need_next_chunk")

          I'm weird. I don't like while statements either.

          • xyz replied to this.

            cybereality I don't like them either but I think it's not possible to make an endless for loop in GDScript 😃

              xyz I think it's not possible to make an endless for loop in GDScript

              	var a: Array = [0]
              	for i in a:
              		a.append(0)
                              print_debug(a.size())
              		yield(get_tree(), "idle_frame")

              The yield is only there to slow down the looping so that the printing is visible and shows that the loop doesn't terminate. Technically, the loop would probably terminate eventually when the array index hits a limit or it runs out of RAM.