ProtoFlux:While: Difference between revisions

From Resonite Wiki
Add Known Issues section to document issue #256
overhaul cleanup etc.
Line 15: Line 15:
|}}
|}}


The '''While''' node will start running when this gets [[Impulses|impulsed]]. The code will continue running and hold a [[Impulses#Context|context]] until the provided Condition is false or the max execution iterations is hit.
The '''While''' node is used to perform looping operations by allowing one to fire [[impulses]] continuously while a condition remains true.


{{Note|If this node just has an [[ProtoFlux:Call Input|Input]] with the [[Type:bool|bool]] type set to true, the code will not be able to stop and will error the entire Flux, and in many cases the entire world or client will freeze (Issues [https://github.com/Yellow-Dog-Man/Resonite-Issues/issues/774 #774] & [https://github.com/Yellow-Dog-Man/Resonite-Issues/issues/1677 #1677]). Caution should be exercised when using this node.|danger}}
For the [[async]] variant of this node, see [[ProtoFlux:Async While|Async While]].


{{Note|If it is easy to determine how often the loop is going to execute, a [[ProtoFlux:For|For Loop]] should be preferred to avoid accidentally creating infinite loops.|suggestion}}
{{Note|Be very careful when developing with this node. [https://github.com/Yellow-Dog-Man/Resonite-Issues/issues/774 There is no iteration limit for debugging] and [https://github.com/Yellow-Dog-Man/Resonite-Issues/issues/1677 ProtoFlux does not have handling for execution taking too long]. If you accidentally create an infinite loop, you'll be unable to save progress or anything else important. Don't connect to an input impulse while debugging and save before testing!|danger}}


== Inputs ==
== Inputs ==
Line 25: Line 25:
=== * ([[Impulses|Call]]) ===
=== * ([[Impulses|Call]]) ===


Impulse to start the loop
Begin the while loop.


=== Condition ([[Type:Bool|Boolean]]) ===
=== Condition ([[Type:Bool|Boolean]]) ===


The value that the loop will check for if it should continue running or not.
Condition that the loop will check to determine if it should iterate again or not. If <code>True</code>, it will iterate again.


== Outputs ==
== Outputs ==
Line 35: Line 35:
=== LoopStart ([[Impulses|Impulse]]) ===
=== LoopStart ([[Impulses|Impulse]]) ===


Fires once at the beginning of the loop, regardless of if Condition ([[Type:Bool|Boolean]]) is true or not.
Fires after <code>*</code> is pulsed and before any iterations are performed. Will be pulsed even if <code>Condition</code> is <code>False</code> at the time of the loop beginning.


=== LoopIteration ([[Impulses|Impulse]]) ===
=== LoopIteration ([[Impulses|Impulse]]) ===


Fires infinitely all in one game tick until the game crashes, or Condition ([[Type:Bool|Boolean]]) is false. Will only fire if Condition ([[Type:Bool|Boolean]]) is true.
Will be pulsed for as long <code>Condition</code> is <code>True</code>. Only after the [[context]] of the current loop iteration is finished will the next iteration fire.


=== LoopEnd ([[Impulses|Impulse]]) ===
=== LoopEnd ([[Impulses|Impulse]]) ===


Fires once the triggered loop has ended and the node has not hit a critical error.
Fires after <code>Condition</code> turns <code>False</code>, continuing the impulse chain from before.


== Examples ==
== Known Issues ==


<gallery widths=480px heights=480px>
* As of the time of writing, there is [https://github.com/Yellow-Dog-Man/Resonite-Issues/issues/256 a known issue] where if the final node in the <code>LoopIteration</code> chain is a [[ProtoFlux:Write|Write]] node, said node modifies a variable used for conditional evaluation, <em>and</em> the value to write is based off said variable, the write will be using a previously cached value. This can cause an extra loop iteration to occur, which is very annoying to debug.
File:Protoflux_example_while_loop.webp|Example of how to use a while loop.
** The easiest way to work around this bug is to add a "dummy" node after the write, such as an [[ProtoFlux:Impulse Display|Impulse Display]] or, if debugging a ton of impulses and lag is undesirable, an empty Write node.
File:Protoflux_example_while_loop_failed.webp|Example of how to not use a while loop, which will crash the game if fired.
</gallery>


== Related Issues ==
== See Also ==


* As the time of writing, there is [https://github.com/Yellow-Dog-Man/Resonite-Issues/issues/256 a known issue] that can occur when the very last node in the LoopIteration chain is a [[ProtoFlux:Write|Write]] node. If the Write affects the value of a variable which is itself used as part of the evaluation of the Condition, the evaluation will use the value that the variable held ''before'' the Write operation is completed.
* If it is possible to determine the amount of times you need to loop beforehand, consider [[ProtoFlux:For]] instead.
** Because this only occurs if the Write node is the very last one in the chain, a simple workaround is to connect any node to the OnWritten output of the Write node – such as a [[Tips & Tricks#Quickly create inputs or displays|Pulse Display]].
 
== Further Reading ==
 
=== Fun Facts ===
 
This node (and even more broadly, code with loops like these in general) has an [[Unsolvable Problem]], specifically the [https://en.wikipedia.org/wiki/Halting_problem halting problem].


[[Category:ProtoFlux:Flow]]
[[Category:ProtoFlux:Flow]]

Revision as of 20:54, 14 December 2024

While
*
LoopStart
Condition
LoopIteration
LoopEnd
Flow

The While node is used to perform looping operations by allowing one to fire impulses continuously while a condition remains true.

For the async variant of this node, see Async While.

Be very careful when developing with this node. There is no iteration limit for debugging and ProtoFlux does not have handling for execution taking too long. If you accidentally create an infinite loop, you'll be unable to save progress or anything else important. Don't connect to an input impulse while debugging and save before testing!

Inputs

* (Call)

Begin the while loop.

Condition (Boolean)

Condition that the loop will check to determine if it should iterate again or not. If True, it will iterate again.

Outputs

LoopStart (Impulse)

Fires after * is pulsed and before any iterations are performed. Will be pulsed even if Condition is False at the time of the loop beginning.

LoopIteration (Impulse)

Will be pulsed for as long Condition is True. Only after the context of the current loop iteration is finished will the next iteration fire.

LoopEnd (Impulse)

Fires after Condition turns False, continuing the impulse chain from before.

Known Issues

  • As of the time of writing, there is a known issue where if the final node in the LoopIteration chain is a Write node, said node modifies a variable used for conditional evaluation, and the value to write is based off said variable, the write will be using a previously cached value. This can cause an extra loop iteration to occur, which is very annoying to debug.
    • The easiest way to work around this bug is to add a "dummy" node after the write, such as an Impulse Display or, if debugging a ton of impulses and lag is undesirable, an empty Write node.

See Also

  • If it is possible to determine the amount of times you need to loop beforehand, consider ProtoFlux:For instead.