Control
Branching
Branching units split the control flow based on a value.
Branch
The common branch unit uses a boolean condition. You can think of them as an if the condition is true, do something, else, do something else.
Switch
You can also branch depending on the value of an enum, a string or an integer. These units are called Switch units, like they are in scripting.
To switch on an enum, you first need to decide the type of the enum. This will make the branch output ports appear:
To switch on a string or number, you first need to create each branch option in the graph inspector:
The unit will then be updated with each output port:
For strings, you can optionally choose to ignore the case of the selector.
Note that a Default port is always added. It is the path that the control flow should take if the input selector does not correspond to any other option.
Merging
Select
Select units are the opposite of switch units. They allow you to select a single value from a set of options based on a selector.
Because they're so similar, we're not going to cover each of them, but here's an example of a Select On Integer unit that chooses a color based on a player number:
Note that predictive debugging here warns you that there will be a crash if playerNo is not within 1, 2, 3, or 4, because we haven't connected the Default port. If we're sure that it never will be for example 5 or 6, we can safely ignore this warning.
Looping
Loops allow you to repeat logic for a certain number of iterations before moving on.
The logic to be repeated is called the body of the loop. After the loop is over, the exit port is called.
Note that the body of every loop is called synchronously, not over the course of multiple frames. Coroutine-like behaviours are instead achieved by listening to the update event manually.
While Loop
While is the simplest form of loop. It will repeat its body while its condition remains true, or in other words, until it becomes false.
For example, this graph generates a new random name until the result isn't contained in the names application variable:
Be careful not to create an infinite loop! If the condition is always true, the editor will hang. Because loop bodies are synchronous, not parallel, there are few uses for while loops in Bolt.
For Each Loop
For Each iterates over every element of a collection. It outputs the current index and item that is being looped over.
For example, this graph will output 3 messages to the console:
- I like cats
- I like dogs
- I like birds
To access the key and value from dictionaries in the loop, check the Dictionary box:
For Loop
For is a numeric loop. It requires 3 integers: a start index, an end index, and a step. The loop will start at the first index, then move towards the last index via increments of the step. It outputs the current index.
For example, this graph will count to ten by skipping odd numbers because of its step. In other words, its output will be 0, 2, 4, 6, then 8.
The for loop can also be very useful when combined to the Get List Item and Count Items units.
For example, this graph is very similar to the last, in that it will output I like {animal}s to the console. However, instead of using the for each unit that outputs each item, we get each item manually by its index in the list. This allows us to specify a different increment (in this case 2) and skip some items. Therefore, this graph will only output 2 messages:
- I like cats
- I like birds
Break Loop
You can tell a loop to finish early by using the Break Loop unit. As soon as this unit is entered, the exit port of the loop will be called, no matter how many more iterations remained.
For example, even though this for loop is supposed to count to 10, it will stop at 5 because of the break. Therefore, its output will be 0, 1, 2, 3, then 4.
Exception Handling
Try Catch
The Try Catch unit allows you to handle an Exception that occurs. It's a good way of preventing your game from crashing in case you know some code might fail.
Anything that gets executed in the Try branch is considered "safe": if it fails, the flow will continue from the Catch branch instead. If that happens, the Exception port will contain information about the failure. A common way of handling it is to log a warning with the exception message, for example:
Note: By default, this unit catches any exception. You can be more specific in your handling by changing the exception type in the dropdown.
The Finally branch is optional. It will always be called after Try or Catch, regardless of whether the operation succeeded or not. It is usually used to dispose or destroy any resources that you need to ensure are freed. You can leave that port disconnected if you don't need that.
Throw
The Throw unit allows you to raise your own exceptions that stop the flow. These can then be caught with Try Catch.
It is good practice to "fail early" by throwing as soon as something unexpected happens. It helps catch bugs early in the chain, instead of letting them trickle down and have unexpected side effects that are hard to debug.
For example, you could make sure a damage is positive before applying it:
If you check the Custom checkbox, you'll be
able to pass a custom Exception object that can contain more data than a
simple message. Most often, this is not required. By default, the thrown
exception is of type System.Exception
.
Toggles
Toggle units are like light-switches: they can be turned on and off to impact either flow or values. You can also think of then as "gates" that can be opened and closed.
Toggle Flow
The Toggle Flow unit gates the flow of control. When on, the flow will pass through; when off, it will not.
In this simple example, the object would start going up when you hit Space, and it would stop if you hit it again.
As you can see, there are many inputs and outputs that allow fine grain control over the logic. In the previous example, we were using Toggle because we wanted the same event (a keypress) to turn the toggle on and off. If we wanted that to be done through two different events, we could have used On and Off instead.
On the output side, the Is On boolean port indicates whether the toggle is currently turned on. The control outputs are triggered according to the table below:
Port | Triggered When |
---|---|
On | Flow enters the toggle via the unmarked input while it is on. |
Off | Flow enters the toggle via the unmarked input while it is off. |
Turned On | The toggle gets turned on, either via the On or Toggle inputs. |
Turned Off | The toggle gets turned off, either via the Off or Toggle inputs. |
Toggle Value
The Toggle Value unit selects between two different input values depending on whether it is on or off. Its ports work exactly like the Toggle Flow unit.
Here's another way of implementing the same logic as the previous example: hitting Space will toggle the object going up. This time, we're doing this with a value of 1 or 0 as the vertical velocity instead.
Note: Turning on relations in the toolbar is a good reminder of the flow between the toggle ports:
Once
The Once unit allows you to execute different logic the first time it is traversed from the subsequent times. For example:
It can be reset by entering the Reset port.
Cache
The Cache unit allows you to save the result of an expensive operating and reuse it instead of fetching it again each time you need it.
For example, pretend we had an expensive formula to calculate, and we wanted to log the result twice. Using this graph, the formula will be calculated twice:
But by using the Cache unit, we can save the result and calculate it only once, optimizing our performance twofold:
Note: It's important to note that caching only lasts within the scope of the current flow. The value of the cache is not shared or available from another event, for example.