This tutorial teaches you how to create your first multiplayer game with Bolt. You'l set up a couple of simple scenes with Bolt, and perform all basic tasks like spawning objects and replicating transforms. For clarity and teaching purposes, code is favored over Bolt's built in automation and testing tools.
This tutorial is intended to be followed using the 'DEBUG' build of Bolt, for more information on the different builds see the Debug vs. Release page. For instructions on installing Bolt for the first time: Installing. For instructions on upgrading Bolt: Upgrading. After installing or upgrading Bolt, you should have a folder structure which looks something like this:
The thing that sets Bolt apart from other networking solutions for Unity is that there's very little actual networking code you need to write by hand. All serialization, interpolation and extrapolation, animation replication, etc, is handled automatically by Bolt.
The only thing you need to do is telling Bolt what you want to replicate over the network. This is done through the Bolt Assets window, which can be found under Window/Bolt Engine/Assets.
Assets are broken down into four categories:
- States, these are the meat of most games built with Bolt, they allow you to define things like name, health, transform, animation parameters, etc.
- Objects, objects are a way of logically grouping several properties in the same way you would do with a C# class. As an example, say that you want to create an inventory for a player in an RPG game, you could create an Object called "Item" and give it properties like ItemId, Durability, etc. You would then on the State create an array of Item objects.
- Commands, these are used exclusively for the authoritative features of Bolt and are used to encapsulate user input and the result of applying the input to a character in the world. Commands lets you implement advanced client side prediction and automatic correction of predicted state.
- Events, we made the decision of going with events instead of RPC's in Bolt. Events allow you to much easier decouple the different parts of your game from each other, as you can have several listeners to a single event active at the same time.
At the bottom of the Bolt Assets window you'll also see the version number of Bolt, whether it's built in DEBUG/RELEASE mode and two buttons for compiling and saving the Bolt Assets.
Right click anywhere in the empty space of the Bolt Assets window and select 'New State'.
Bolt will create a new state called 'NewState', and pop up the Bolt Editor window for you with that state active.
Change the name of the state to 'CubeState' in the text field at the top and then click 'New Property', name the new property 'CubeTransform' and set it's type to 'Transform'. Leave the rest of the settings as is.
If you accidentally added more than one property or an assets you don't want, hold down the Ctrl key on your keyboard and a little red X will pop up next to all assets and properties allowing you to delete them.
To make Bolt aware of our state and property we need to compile it, this can be done either through the Assets/Bolt Engine/Compile Assembly menu option or with the little green arrow icon in the Bolt Assets window. They both do the exact same thing.
When compiling Bolt will output a couple of messages in the Unity editor console.
Go to the Project tab in Unity and create a folder called 'Tutorial', with two sub-folders 'Scripts' and 'Prefabs'.
The first thing we are going to do is to create our prefab for Bolt, it's just going to be a standard Unity cube. Create a new cube from the GameObject/Create Other/Cube (v5 GameObject/3D Object/Cube) menu, then drag it in from the Hierarchy into the 'Tutorial/Prefabs' folder in the Project tab. You can delete the cube left in the Hierarchy when this is done.
To make Bolt aware of our 'Cube' prefab add a 'Bolt Entity' component to it, click Add Component and look up the component up by name.
Since this is the first time Bolt sees our 'Cube' prefab it will give you a couple of errors in the 'Bolt Entity' editor. The two errors below the 'Prefab Id' field are resolved by running the compiler for Bolt, either through Assets/Bolt Engine/Compile Assembly or the green arrow icon in the 'Bolt Assets' window. The error under the 'Serializer' (v5 State) field is resolved by selecting the ICubeState serializer (v5 state) from the drop-down where it says 'NOT ASSIGNED' currently.
There are a bunch of settings on the 'Bolt Entity' component we can change, but we really don't need to as the defaults are what you want on almost all prefabs and types of games. The settings mostly deal with special cases that we have descriptions for in the more advanced sections of this documentation.
Before we continue with some actual C# code, let's just set up a simple scene in Unity to spawn our cubes into. Create a new unity scene and save it to 'Tutorial/Tutorial1'.
In our scene create a new plane from GameObject/Create Other/Plane (v5 GameObject/3D Object/Plane) and a new directional light from GameObject/Create Other/Directional Light (v5 GameObject/Light/Directional Light). I also create a new material for the plane and saved that to 'Tutorial/Tutorial1_Plane' so we can give it a different color than the cubes.
I highlighted the settings i changed for the Main Camera, Plane and Directional Light in my scene here:
Now it's time to write some code, create a new script called 'NetworkCallbacks' in the 'Tutorial/Scripts' folder and open it up in your text editor of choice, clear out the default unity methods so that your file looks like below.
We are going to change the base-class from
Bolt.GlobalEventListener class itself does inherit from
MonoBehaviour so you can do all the normal Unity stuff as usual, but it adds several Bolt specific methods on-top.
What we want to do is to receive a callback when a scene is loading (in this case our 'Tutorial1' scene) so that we know when we can instantiate our 'Cube' prefab. Bolt supports automatically networked loading of Unity scenes, the callback we want to hook into for this is called
It's important to note here also that Bolt uses the
public override standard C# way of implementing methods, instead of the Unity way where you don't designate a method as an override.
To instantiate a prefab in Bolt you use the BoltNetwork.Instantiate method, in general it works exactly the same as the built-in GameObject.Instantiate in Unity. There are several different overloads for this method with various parameters, but we are going to use one of the simpler ones: It takes a Bolt prefab reference, position and rotation.
We randomize a position on the XZ plane so that everyone doesn't spawn at the same position, we then call
BoltNetwork.Instantiate with a reference to our Cube, the random position and a default rotation.
The usage of
BoltPrefabs.Cube might look a bit weird if you are brand new to Bolt.
BoltPrefabs is a static class which is compiled and updated by Bolt when you run Assets/Bolt Engine/Compile Assembly. It contains a unique reference to each prefab with a Bolt Entity on it. You could also pass in a normal GameObject reference to the prefab instead if you wanted to.
There's one last thing we are going to do before we are done with the
NetworkCallbacks script, we are going to add an attribute to it called
[BoltGlobalBehaviour], on the line above the
public class NetworkCallbacks ... definition add the attribute.
What this attribute does is that it allows Bolt to automatically detect this script and create an instance of it which lives together with Bolt and is destroyed when Bolt is shut down.
Important: You should not manually attach an instance of this script to any GameObject in Unity, it will be handled by Bolt automatically. If you want to manually attach a Bolt.GlobalEventListener somewhere then you should not add the
The last step we need to perform before we can test our Cube spawning is to just setup a main menu script that starts Bolt. Create a new scene and save it to 'Tutorial/Tutorial1_Menu'.
Before we go any further and write some code for our Menu, make sure that both the 'Tutorial1' and 'Tutorial1_Menu' scenes are added to the Build Settings in Unity.
Important: After you've added both scenes, make sure to run Assets/Bolt Engine/Compile Assembly again to make Bolt aware of your scenes. Also, make sure that the 'Tutorial1_Menu' scene is the first one so that it loads when your game starts.
We're going to create a super simple menu script and attach it to the MainCamera in the 'Tutorial1_Menu' scene. Create a script called 'Menu' in 'Tutorial/Scripts'.
Clear out the default Unity methods and add an OnGUI method. We're going to simply create two buttons which stretches over most of the screen, one for starting the server and one for starting the client.
All the GUILayout.* calls are standard Unity stuff so we'll skip that, the two important pieces of code are inside the two if-blocks.
The server is started by calling
BoltLauncher.StartServer, and then passing in and end-point (an ip-address + port) that it should listen on, after we've started the server we call
BoltNetwork.LoadScene("Tutorial1") which tells bolt to load the 'Tutorial1' scene.
The process on the client is pretty similar to the server, we call
BoltLauncher.StartClient but in general you do not need to assign a specific end-point to the client and can let the operating system guess one. We then connect to the server with
BoltNetwork.Connect and pass in the same end-point as we passed to
BoltLauncher.StartServer when we started the server.
Attach our 'Menu' script to the 'MainCamera' game object in the 'Tutorial1_Menu' scene.
Important: Make sure it's the correct scene you attach the 'Menu' script to.
Before we start our game make sure to go into the unity 'Player Settings' and enable 'Run In Background'.
Build a standalone desktop version of the game and start two instance of it. On windows you will most likely get a 'Windows Firewall' popup, just click 'Allow access'.
Make sure you are running in 'Windowed' mode, and also pick a resolution which is in 16:9 format like 1280x720.
When the game starts click 'Start Server' on the first one and 'Start Client' on the second one, you should now see two instances of the game running, two cubes spawning (one for each instance of the game).
You will also see the 'Console' which bolt adds by default when running in DEBUG mode, and a little 'Bolt Performance' display at the bottom. If you hover the small Bolt icons with your mouse cursor Bolt will also display debug information about the state of the object (press HOME key).
Continue in 'Bolt 102 - Properties and callbacks'.