2. Character Controller

The first thing we'll do is create a character controller.

This controller will handle:

  • Moving left and right
  • Jumping
  • Playing the right animations

Before this part of the tutrial, read the following article of the manual. It takes about 5 minutes and it will give you the very basic notions you need to know about graphs, machines and macros. 

Manual: Graphs, Machines & Macros

1. Create a flow machine

For the player controller, we will use a flow machine.

Select the Player object in the hierarchy, and click Add Component > Bolt > Flow Machine:

The graph window should now display an default graph with Start and Update events:

2. Convert the source to a macro

This is a bit of a boring step, but it's crucial to Bolt. It only takes a few seconds, but make sure you understand what's happening.

Because the player is a prefab that we will reuse across many scenes, we need to use a macro instead of an embed as our source. This is a simple rule of thumb in Bolt: when using prefabs, you should use a macro instead of an embedIf you want more information about why, you can read the following manual article:

Manual: Prefabs

Converting is very easy. In the inspector for the flow machine, click Convert next to the Source property:

Then, save the macro under Macros / PlayerController.

The machine component should then look like this:

Now that our machine is created, apply the changes to the player prefab:

We will repeat this process often in the tutorial for the different graphs we create. From now on, if you see "convert your graph to a macro", use the same process that we described here.

3. Calculate the movement

We want the character to move left and right, depending on the horizontal input axis. The horizontal input axis is a pre-configured Unity input shortcut that represents, for example, A and D on a keyboard, or the left joystick on a controller. When you go left, it returns -1, and when you go right, it returns +1. How fast to move will be controlled by a speed variable that we can tweak to adjust the gameplay. 

If you're not familiar with Unity input, remember you can see and edit the available axes and buttons from Edit > Project Settings > Input:

Let's get started.

Because this is the first time we create a variable and add units to our graph, we'll show you every step along with gifs. But to speed things up for the rest of the tutorial, after this section we'll only give you the steps and the final screenshots.

The first thing we need to do is create the speed variable on our player game object:

  1. Select the Player game object 
  2. Switch to the Object tab in the variables window
  3. Add a new variable named Speed
  4. Set its type to Float
  5. Give it a value of 5

For more information about variables, have a look at this article in the manual:

Manual: Variables

Then, we need to get the horizontal input axis. We can do that with the Get Axis unit. 

  1. Add the unit to your graph by right-clicking in an empty space and navigating to Codebase > Unity Engine > Input > Get Axis
  2. Type Horizontal in the axis name field.

You can also search for get axis and let the fuzzy finder to the work for you:

You will notice the new unit shows up as dimmed out. This is because we're not using its value anywhere yet, so Bolt warns us that is is currently useless by fading it out. If you want, you can disable this by toggling off  in the graph toolbar.

Next, we need to multiply this value with our speed object variable. We can use Bolt's contextual menu to make that easier.

  1. Drag and drop the value output port of the Get Axis unit to an empty space in the graph
  2. Choose Multiply
  3. Drag and drop the second port of the Multiply unit to an empty space in the graph
  4. Choose Variables > Get Object Variable
  5. Type Speed as the variable name

To complete our movement calculation:

  1. Add a Set Graph Variable unit (under Variables)
  2. Set its name to Movement
  3. Connect the result of the multiplication to its value input port
  4. Connect the Update node to its control input port

Note: Variable units have been improved in v.1.2 after this tutorial was written. They should look slightly different (with dropdowns), but they are functionally the same.

Let's recap what's happening here:

  1. At every frame (Update event)...
  2. ... we get the horizontal input axis (which is within -1 to +1)...
  3. ... we multiply it with the speed (so it becomes -5 to +5)...
  4. ... and store it in a variable called Movement.

Our player isn't moving yet, but we know by how much it should move.

Note two important things about the new movement variable:

  • We didn't create it beforehand like we did for the player's speed, because we didn't need to give it a default value. Bolt supports dynamic variables, meaning you can create new variables during play mode on the fly by just assigning them a value like we just did.
  • We used a graph variable instead of an object variable, because we will only ever need the movement inside this graph -- no need to share it with the outside world.

Whew. This was pretty boring, but now you know all the basics: creating graphs, variables and units. Now, we'll pick up some speed and actually make something happen.

4. Moving the player

The player prefab in the project already has a Rigidbody 2D component attached. All we have to do to make the player move is tell it at which velocity (speed) to go... and we just calculated that!

Velocity on 2D rigidbodies is a 2D vector: it has a X component for the horizontal speed, and a Y component for the vertical speed. Because we only want to affect the horizontal speed, we'll have to keep the vertical speed intact.

Here is the graph we need:

  • Get Graph Variable is located under Variables
  • Get Velocity and Set Velocity are located under Codebase > Unity Engine > Rigidbody 2D
  • Get Y and Create Vector 2 are located under Codebase > Unity Engine > Vector 2

If you have  enabled, you'll notice all of this graph is faded out. That's because we never specified when to set the velocity (the first arrow port on the Set Velocity node). Quite simply, we want to do this after we calculate the movement, so we can connect it with our previous set of units:

Now that our graph is getting a bit more complex, it would be a good time to start organizing bits of logics in group. The left part is used to calculate the movement, and the right part is used to set the velocity. By holding Ctrl and dragging, you can create groups than can be labeled:

We're ready to test! If you enter play mode now, you should be able to move the player with the keyboard or a controller:

If you keep the player selected while in play mode, you'll see our graph now animates its active nodes and connections:

5. Flip the direction

Next we'll add a new part to our graph to flip the player in the direction of the movement.

To do so, we only have to change the scale of the player game object on the X axis.

When going right (movement > 0), the scale should be +1, because the sprite is already facing right.

When going left (movement < 0), the scale should be -1, so the sprite gets flipped to face left.

When not moving (movement = 0), the scale should not change, so the player stays in the direction of the last movement.

The Y and Z axes of the scale should remain at 1.

Here is the graph we need:

  • Set Local Scale is located under Codebase > Unity Engine > Transform
  • Create Vector 3 is located under Codebase > Unity Engine > Vector 3
  • Branch and Select are located under Control
  • Comparison is located under Logic
  • Float literals will be at the root of the options if dragged contextually from the Select node

Then, connect the control input of the Branch node to the control output of our previous Set Velocity node on the left, and add a Flip group to keep things tidy:

If you play now, you should see the player flip:

6. Playing the animations

The last part of our movement graph will be to play the run animation.

The player prefab is already set up with a proper Unity animator controller. This controller has a Speed parameter that is used to transition between Idle and Walk states:

All we need to do on Bolt's end is to pass our movement speed to the animator. Because we're passing a speed and not a direction, we'll need to make our Movement variable absolute before passing it. This way, if we're going left at -5 movement, we'll tell the animator we're going at 5 speed.

  • Set Float is located under Codebase > Unity Engine > Animator
  • Absolute is located under Math > Scalar

To connect this part of the graph with our movement code, we'll need to add two connections:

  1. To the True port of our no-movement check, in case we skipped flipping the player
  2. To the output port of the Set Local Scale unit, in case we did flip the player

This way, whether or not we flip the player, we'll still update the animation. Bolt supports connecting multiple control outputs to a single control input for these kind of scenarios.

With an Animator group around or last part, your graph should now look a bit like this when zoomed out:

If you test now, the animations will play properly. Movement code: check. Hurray!

7. Jumping

Because our player is a physics rigidbody, implementing jump is as easy as adding an upwards vertical force.

First, create a new float object variable called Jump and give it a value of 12:

Then, below our movement graph, add a new group with the following units:

  • On Button Input is located under Events > Input
  • Add Force is located under Codebase > Rigidbody 2D > Add Force

Just like the Horizontal axis we used before, Jump is a default Unity input for new projects, mapped to Space on the keyboard. If you test your game now, you'll be able to jump!

8. Ground Check

There are two problems with our jump code:

  1. It doesn't change the animation sprite when you're in the air
  2. It allows you to jump again while you're already in the air

To fix this, we'll need to create a ground check. This part of the graph will use a raycast. This means we will throw a ray from the player's belly towards the ground, and check if we hit a platform within a small distance. If we did, it means the player is grounded; otherwise, it's in the air.

To make our raycast more reliable, we'll actually use what is called a circle cast. It's basically the same as a raycast, except you can give a thicker width (radius) to your ray. The node we need is called Circle Cast, under Codebase > Unity Engine > Physics 2D:

There are many options for it, depending on what parameters you need. In our case, we need the one with:

  • Origin: The source of the circle cast, in our case the player's position
  • Radius: The width or the circle cast, which we'll set to 0.3 for more reliability
  • Direction: The direction in which we'll cast, in our case down (-1 on the Y axis).
  • Distance: How far the circle cast will check until it stops, which we'll set to 1.1
  • Layer Mask: On which layer(s) it should check for a collision, which we'll set to Platforms only.

Once properly setup, our circle cast should look like this:

To get the layer mask dropdown, search for Layer Mask and choose Layer Mask Literal.

This graph can be read as: "Throw a ray downwards from my position with a 0.3 thickness, and check if it hits an object on the  Platforms layer within 1.1 units". 

Next, we need to analyze the result. Drag the little target output port to get the contextual menu open, and choose Raycast Hit 2D > Expose Raycast Hit 2D:

This will expose all the items in the raycast hit result. To check whether we actually hit a platform, we only need to check if the Collider is equal to Null (none). If it is, we didn't hit a platform and the player is in the air. If it isn't, we found a platform below our feet and the player is therefore grounded.

  • Not Equal is located under Logic
  • Null is located under Nulls

8.1 Preventing double jump

You can then use the result of our ground check to limit the jump to when the player is grounded:

Now, the player can't double jump anymore!

8.2 Setting the jump sprite

We also need change the sprite when the player is in the air. The animator controller is already configured to take a Grounded bool parameter. The only thing we need to do from Bolt is assign it. To do that, we'll copy-paste our ground check code at the end of our previous animator section, then use the Set Bool unit.

Now, if you test your game, the jump sprite should show up when in the air:

8.3 Reusing the ground check with a super unit

In scripting, there is a very important principle called DRY: Don't Repeat Yourself.

What we just did to change the jump sprite broke this principle: we copied and pasted the same part of our graph twice.

Now, if we wanted to make adjustments to our ground check code, we'd have to change two places every time. This may not seem so bad now, but what about when we'll have enemies doing multiple ground checks too? We'd have to update our graphs in three or four or even more places every time we make a change. Yikes.

Fortunately, Bolt provides a way to reuse the same graph in different places called Super Units. We will use super units to turn our ground check graph into a single unit that we will use for both the double-jump prevention and the jump sprite.

First, create a new macro with Assets > Create > Bolt > Flow Macro, and call it GroundCheck:

Then, copy the ground check units from the player graph, and paste them in the ground check graph:

Go back in the player graph, and delete your ground checks. Instead, drag & drop the new GroundCheck macro into your graph. It should appear as a single node, for example like this for the jump:

We have a problem here... Where is the result of the ground check? How can we connect it to the Branch node?

The reason it's not visible is because we haven't created an Output unit in our ground check macro. Let's do that now. From the player graph, just double click the Ground Check super unit to open its full graph. Notice the breadcrumbs in the toolbar let you navigate in nested graphs easily:

Next, add an Output unit, located under Nesting, and select it to display its graph inspector:

We will add a Value Output  for the result of the ground check. Set its key to groundedand its type to Boolean. If you want, you can give it a label and summary to add documentation to the graph inspector. Lastly, connect the new grounded port with the result of the ground check.

Navigate back to the parent player graph using the breadcrumbs in the toolbar. You'll see the super unit now has a grounded output port. Use that to connect it for both the double-jump prevention and the jump sprite animation:

If you play your game now, nothing should have changed. But your graph is now a lot cleaner, DRYer, and easier to maintain for the future. 


Finally, apply the changes to your prefab so that the object variables like Speed and Jump we created are automatically added on other player prefab instances in the other scenes.

This concludes the character controller. In this part, you learned how to:

  • Create machines and macros
  • Create and work with variables
  • Add units and connections
  • Reuse graphs with super units
  • Work with input, math, animation, physics and raycasting

Whew! The ice is broken, and you now know most of the basic concepts you need to use Bolt. Take a moment to review what you've learned, make sure you understand, and stretch your legs. Next up, we'll be adding a death mechanic to our games. 

Project Setup Spikes & Death

This article was helpful for 32 people. Is this article helpful for you?

8.1 Preventing double jump took me a long time to figure out that I need to delete "Jump" group we made before and replace it with "Add Force". There is no mention of that. Would be cool if You fix that!


I got lost at that point too, I had no idea the "add force" group was supposed to replace "jump" either. Thank you for posting this!


The "Jump" Group is just renamed to "Add Force" since jumping is just an add force function.  You don't have to delete that group, you can just rename it.

I cannot achieve this:

8.1 Preventing double jump

The character is still able to make double jump.

I am trying this tutorial through script, can some one post a code version for double jump checking.

This is to check strength of VS tool.


I can't find Vector2>Get Y...

What is in your options for Codebase > Unity Engine > Vector 2?

What show up if you search for Get Y?

Hi thanks for the tutorial. Can anyone help me why the parented camera doesnt flip when we are flipping the player? i am trying to create one from scratch but my camera flips . did i miss something in the tutorial? some help will be very much appreciated

Nevermind it wasnt a problem at all unless i parent another object to the camera itself. i will try to figure out something as its not part of this tutorial. :)

I'm pretty excited to learn how to program, but early on I'm already having an issue where Unity doesn't seem to be accepting my spacebar input for Jump. I press space and nothing happens; all other controls work. Project Input shows Jump is mapped to space (although it seemed to be mapped to x axis originally before I fixed that.) Either way, nothing happens. Is something wrong?

Aha! I think I figured it out. In the tutorial, it says Rigidbody 2D is found in Codebase. If I use the one under Player instead, it works.

I reached the part where I test the left and right movement, but upon entering Play Mode and pressing A/D nothing happens. I check the console and I get this message:

ArgumentException: No variable name specified.
Parameter name: variable
Bolt.VariableDeclarations.Get (System.String variable)
Bolt.GetVariable.Get (Ludiq.Recursion recursion)
Bolt.Unit+<>c__DisplayClass56_0`1[System.Object].<ValueOutput>b__0 (Ludiq.Recursion recursion)
Bolt.ValueOutput.GetValue (Ludiq.Recursion recursion)
I'm unable to specify the variables in Get Variable. I'm confused and I don't know how to fix this problem. :(


 I had the same problem and found out i wrote horizontal instead of Horizontal with capital H at the beggining, 

check your writting is the same as the tutorial!

Hope this helps!

I checked to see if mine was the same but it appears that I already spelled Horizontal correctly and with a H.

did you solve the problem? i got the same error

Im afraid not, sorry. I abandoned the tutorial a few weeks ago; figured there's no point following a tutorial for a previous version of Bolt.

I ran into a problem here: Layer Mask: On which layer(s) it should check for a collision, which we'll set to Platforms only.

There was no 'Platforms' layer option in the drop down. I looked and there didn't seem to be any layer in the project called Platforms. I created one, and put the platforms on it, and it seems to be working - is this the correct solution, or did I miss something that was already there?

That is the solution, but you should have had that set up from Section 1.3.  You might want to double back and check your layers to make sure you aren't missing any others.

I'm working on a platformer for a university class and I'm completly new to game making. For a reason (I don't really want to explain now, it's complicated) I don't want to flip my character, but assign different animations for left and right. So instead of a flip, I need to define L and R for my Animator. Any ideas how to do this? Deadline is soon, so I really appreciate fast help: )


In section #5 can someone explain the purpose of the "Branch" node. I'm new to programming. Purely as a novice, it makes sense that if A < B it would flip the scale to -1/1. That said, if I remove the "branch" it clearly breaks. 

But I don't understand is why. If I remove the branch, I see signal is getting passed on (from the A <B comparison to the Select. To me it reads as if a signal is being allowed to pass, despite no movment (thus being neither greater or less than). Which is confusing to me.  Appreciate any help. 

What are you doing in in 4.1 there is not Codebase option i can see i am using 1.2.2 bolt version

There is not Option for Codebase when i select the player and right click in the Graph editor why is this happening??

I'm having the same issue. This is what it's giving me:


When reopening the project I realized the Bolt wizard appeared again. In the Wizard, make sure you click generate under the Types tab. It resolved the issue for me.

Indeed, it just means your unit options database was not generated yet. You can also generate it from Tools > Bolt > Build Unit Options.

This Visual Scripting Tool is Useless i'd Prefer to Write Code over this. the Interface is Poor, it slows down the Unity Editor. Today is my 2nd day with Bolt. and i am leaving today. I could have used my money elsewhere.

Hi Nalayak, I'm sorry Bolt does not meet your expectations. Can you explain tell me more about why you feel the interface is poor in a private ticket? Thanks!

I liked the tutorial and I'm enjoying getting used to Bolt, I must note that the walking animation had a terrible keyframe setup and the character "blinked" out of existence at frame 8 or 9.  Went back and fixed in it the animator. Other than that everything seemed to work as explained.

Hi Christian, thanks for the report, fixing this & reuploading the template package.

Tutorial is great (I much prefer text based tutorials to video ones), but for anyone struggling with the initial jump not doing anything please note that setting this to 12 is not enough to get the initial imported character off the ground. You'll either need to lower his mass, or change the jump value to 300.

Hi, in item 8, part "search for Layer Mask and choose Layer Mask Literal." Dont have option the platform, have other mode?

resolve, "name to layer" and add string, sorry