Show Sidebar

Bolt 105 - Animations

Bolt has built in support for replicating mecanim animations over the network, in this chapter we will look in detail on how you can play your animations over the network properly.

The first thing we need to do is to download a package that contains a model and some animations. This has just been ripped out of the Unity 'Stealth' sample from the asset store. If you prefer you can download the 'Stealth' package from the asset store and export the character yourself, or download this package:

For the rest of this tutorial we will assume that you downloaded the package above. Import the package into your tutorial project,

Find the 'char_robotGuard' prefab in the 'Tutorial/Robot/Done/DonePrefabs' folder and drag it into our 'Tutorial/Prefabs' folder and then rename it to 'Robot'.

Open up the 'Bolt Assets' window and create a new state, call it 'RobotState'. After you have create and named the state find the 'Import Mecanim Parameters' setting on the state itself.

Drag the mecanim controller for the Robot into the slot, you can find it in 'Tutorial/Robot/DoneAnimations/DoneEnemyAnimator'.

Click the 'Import' button.

Bolt will automatically import all the parameters in the mecanim controller for you into the state.

After you imported the parameters from the animation controller a new setting pops up on the state called 'Mecanim (State Wide)', this lets you control if you want to use the normal mecanim methods like animator.SetFloat and animator.SetBool to change the animator values or if you want to use the bolt state properties instead.

If you are adding Bolt to a game that already exists and that's using the standard mecanim way of setting parameters on the animation controller it is best to leave this at the default 'Using Animator Methods' setting. If you are building a new game with Bolt you should usually pick the 'Using Bolt Properties' option, which is what we will do here.

You will see that all of the parameters added by the import also get changed to 'Using Bolt Properties', you also get an additional option for controlling the mecanim damping time of the values. If you want you can run Bolt in 'Mixed Mode' where some properties are set to 'Using Animator Methods' and some are set to 'Using Bolt Properties', in general we advice against this due to the confusion that can arise.

The last thing we need to do is to add a 'Transform' property to our 'RobotState', we do the same as for the 'CubeState' before.

  1. Click on 'New Property' at the top
  2. Name the created property 'Transform'
  3. Set the type of the property to 'Transform'
  4. Set 'Smoothing Algorithm' to 'Interpolation'

Before we continue we need to do some configuration of our mecanim parameters also. First we want to disable network replication for the 'Shot' and 'AimWeight' parameters, as these are controlled by curves inside of the animations and not directly by the user. We don't actually use these parameters in the example, but if we don't disable them mecanim will complain as Bolt will try to set them.

There are two ways of disabling them, the easiest is just to remove them. The other way you can disable them is to set the 'Mecanim' setting to 'Using Animator Methods' and then 'Replication' to 'Local'. This means that Bolt will read out the values from the curves and expose them in properties for you, but it will not send anything over the network.

The second option we need to configure is the 'Damping Time' on the 'Speed' and 'AngularSpeed' property, set it to 0.1 on both.

Important: We are now done with the state for the robot character, make sure to compile Bolt before continuing.

It's time to setup our 'Robot' prefab as a Bolt Entity, select the prefab in the 'Tutorial/Prefabs' folder and add a 'Bolt Entity' component to it.

Change the 'State' setting on the 'Bolt Entity' component to 'IRobotState', and then compile Bolt again to get it to pick up the 'Robot' prefab.

Before we try out spawning our Robots in the world, we need to just tell Bolt to instantiate our new 'Robot' prefab instead of the old 'Cube' one. We do that by going into our NetworkCallbacks script and changing the BoltNetwork.Instantiate call to reference BoltPrefabs.Robot instead.

If we build our game and start two instances, you should see something like below. Bolt will also report the following error to you, because we have not properly assigned an 'Animator' that we want to use to Bolt.

Create a new C# script called RobotBehaviour in the 'Tutorial/Scripts' folder and like we did with our CubeBehaviour remove the default Unity methods and make the class inherit from Bolt.EntityBehaviour<T>.

We are now going to override the Attached method and setup both our 'Transform' property and assign an animator to the state for Bolt to use. The transform is assigned with state.Transform.SetTransforms(transform) like we did before with the CubeTransform property. The animator is assigned by calling state.SetAnimator and passing in the existing Animator component from our prefab.

We also want to make sure that 'root motion' is only used if you are the Owner, as otherwise the motion applied by it would be doubled on all remote peers seeing an entity, we simply assign entity.isOwner to the state.Animator.applyRootMotion property.

We also need to the RobotBehaviour component we just created to the actual 'Robot' prefab.

If you build and start the game now, our robot will keep standing still but we won't see any warnings. The last thing we need to do is to just add the code for controlling the root motion. We open up our RobotBehaviour again and implement the SimulateOwner method. The code in this method might look complex at first, but it's pretty simple.

  1. If W is down, we increase our speed (towards +1.5)
  2. If W is not down, we decrease our speed towards 0
  3. If A is down, we change our angular velocity to negative (towards -1)
  4. If D is down, we change our angular velocity to positive (towards +1)
  5. If neither A or D is down, we move our angular velocity towards 0

At the start of the method we read out the state.Speed and state.AngularSpeed and store them in two local variables, we do this simply because it's easier to work with. At the end of the method we assign them back into the state and clamp speed between 0.0 and 1.5f, and clamp angularSpeed between -1 and +1.

If we build our game again, we can now walk around with the robot character using the WAD keys, below is a YouTube video of the result.

 To Document Top