I don't understand 'while' - it keeps crashing the game.

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

I need it for this function:

func _end_blocked():
	while distancebetween < 10:
		translation.z += 20 * time    #time is delta

I don’t want to put this into _process, because this needs to only be executed at the end of a very specific animation, until it reaches the appropriate spot depending on where the player is.

From what I understand, while is a loop method that will continuously execute a statement until requirements aren’t met any longer to execute. So, why does this freeze my game without even, seemingly, attempting to play the statement?

Is your animation attempting anything like teleporting? if the answer is no you probably do not even need the while loop. So from what I gather you are translating something by 20 until you get to the desired distance, all in a single frame/process loop. Which seems weird. Also you might be locking the processing depending on how distancebetween is calculated, as in does it depend on physics, it might never update to what you expect to happen.

tastyshrimp | 2019-12-25 20:30

The function i posted is incomplete. I’m actually interpolating the translation.

But I thought the while method would cycle the expression until it’s not valid. Can you explain how while is supposed to function, if I’m incorrect?

Thank you for helping.

Dumuz | 2019-12-25 20:45

You are correct about how the while loop works. But what I meant is that your distancebetween might not be changing between executions of the while loop because it depends on changes in the physics space (stuff actually moving), which won’t happen until the next physics pass. You can easily identify this by printing or adding a debugger inside the while loop and checking the value of distancebetween

tastyshrimp | 2019-12-25 20:51

distancebetween is a var i have the _process function updating every frame. It’s just a node.distance_to(node). It should be updating. Unless there’s something I’m missing.

Does the while loop, shut out process from updating?

Dumuz | 2019-12-25 20:59

Yes, while blocks the execution of everything in the thread (assume everything for simplicity) until it returns. So if you depend on anything outside the while loop to change the value you check in the while loop, it will never happen.

Also, _process and _physics_process are both executed in a loop, in different times (check the docs if interested exactly when), so you don’t need to use a while for most stuff, you just wait for the next call of process to do it for you.

tastyshrimp | 2019-12-25 21:04

Hmmm, I see.

Then if I’m trying to have this function:

func _end_blocked():
	while distancebetween < 10:
		transform.origin = transform.origin.linear_interpolate(transform.origin + Vector3(0,0,20),time)

How would I be able to run it outside of the _process function? I only wanted to access it under very specific calls and would like not to have to have an array of if/else statements for this very particular event. But when it does access, it needs to loop the function until i get the desired positioning. Does that make sense?

Also, does the while method work like _process than? Playing every frame until the loop ends?

Dumuz | 2019-12-25 21:19

About the while method first, it blocks your execution at that point, it executes until the loop ends and block the frame (btw, _process does executes every frame, _physics_process does). In a very simplistic manner you can think of the Godot engine doing something like this:
engine.gd

while true:
    for node in get_all_nodes():
        node._process()

Note: This is an oversimplification but i want to show that there is something akin to a while loop calling the _process method from time to time.

About your specific problem, I’m not sure of the best way to solve it, but for me to understand better, you want to execute that check only after an animation finishes playing and keep executing it until it is true, no matter what happens in the mean time, like a different animation playing or whatever?

tastyshrimp | 2019-12-25 21:53

I’m still pretty new to scripting in general, so I don’t full understand the line: for node in get_all_nodes(): I just never got around to understanding the for method, and is get_all_nodes() a function in this statement?

To answer your last question and to be more specific in what I’m trying to do: Is move a mesh while it’s still animating to a specific place relative to where the player is. This way the animation plays smoothly along with the lerp of the function I’m trying to make.

So, I have a call keyframe in an animation that calls to the function I’ve shown you previously. I would just key frame the last movement, but it needs to end up 10 spaces away from where the player is, by the time the animation is done, ready to receive other RNG driven inputs. I think I found a work around for this already, but I was hoping to better understand how to do something like this with the while method, in case something else comes up in the future.

Dumuz | 2019-12-25 22:16

Ok, so for the for, just think of it as a complicated while in that case it would be doing something like:

var nodes = get_all_nodes()
var node = nodes[0] #first node
var index = 0 #where are we
while index < nodes.size() # go through all the nodes in the list
    #do something
    index += 1 # increment index so we leave the loop at some time

About your problem, so you want to execute once per animation frame, so basically, if doing in the _process method you would:

func _process(delta):
    if special_animation_is_playing() && distancebetween < 10:
         transform.origin = transform.origin.linear_interpolate(transform.origin + Vector3(0,0,20),time)

So that would the simple way and it should work, try it first and improve your code later. On another note, think about moving this function into the _physics_process(), check this other question for an explanation why.

Now for the improvement, i didn’t play much with the animation player and it’s calls, so I can’t give you an answer, but what you want seems to be a signal or a method call that is executed every keyframe of an animation, and done by animation itself. I suggest you hit the docs or make another question specifically for that.

tastyshrimp | 2019-12-25 22:32

Hey, thank you for your thorough help and clear explanations on many of questions. You’ve helped me really process (pun intended) everything. Though, I’m sure I’ll have more questions in the future as my project gets more complex. This really helped.

If you replied originally as an ‘Answer’ I’d have voted you best answer. Thank you!

Dumuz | 2019-12-25 23:06

:bust_in_silhouette: Reply From: tastyshrimp

Excerpt from the comments to have the question closed, check comments for whole explanation:

Is your animation attempting anything like teleporting? if the answer is no you probably do not even need the while loop. So from what I gather you are translating something by 20 until you get to the desired distance, all in a single frame/process loop. Which seems weird. Also you might be locking the processing depending on how distancebetween is calculated, as in does it depend on physics, it might never update to what you expect to happen.