PNMS Guide 2.3

Introduction

Welcome to the guided tutorial for the Pro Mounting System version 2.0 for Unreal Engine 4.25 through 4.27.  In this tutorial we will go over the bare bone setups for getting up and running with the plugin.  To follow along you will need to have purchased the plugin from the Unreal Marketplace.  You can then create a new project or download my starting project from the link below.  There will also be a guide on setting up a project independent of the starting project.

Before beginning I highly suggest you look take a look at the Additional Resources for demo project downloads and the Concepts article.

Additional Resources

Concepts


Table of Contents

Because this is a fairly long tutorial to get everything setup.  Here is a Table of Contents for easy jumping around.

1.0 Project Tour

1.1 Mannequin Animations

2.0 Create the Basic Assets

3.0 Interface Component Setup

4.0 Implement the Player Controller

4.1 General Setup

4.2 Unified Controller Pawn Interface

4.3 Rider Controller Interface

5.0 Implement the Rider

5.1 General Setup

5.2 Character Unified Interface

5.3 MountRider Interface

6.0 Mount Setup

6.1 General Setup

6.2 Mount Unified Interface

6.3 Mount Interface

7.0 Seat Setup

7.1 Setup Sockets

7.2 Define Mount Seats

8.0 Animation Setup

8.1 Event Graph

8.2 Anim Graph

8.3 Locomotion States

8.4 Assign the Animation Graph

9.0 Setup Complete


1.0 Project Tour

The Finished project starts with a built in Blueprint Tutorials to get you familiar with the project.  I highly suggest you click on them to get an idea of where everything is and what it does. 

Blueprint Tutorials
Fig 1.0.1 Blueprint Tutorials

 

For the Starting project itself it is much more stripped down and bare bones.  But some of the key things that you will need to know about follows

1.1 Mannequin Animations

I have built and provided a series of mounting, dismounting, and sitting animations for you to use which include direction based mounting and dismounting for getting (in / on), (off / out) of your mount or vehicle.

Check out these animations at “Content/Mannequin/Animations”.  They include the following:

  • AM_Horse_MountLeftSide
  • AM_Horse_MountRightSide
  • AM_Horse_DismountLeftSide
  • AM_Horse_DismountRightSide
  • AM_Horse_MoveToFrontSeat
  • AM_Horse_MoveToBackSeat
  • A_Idle_HorseDriving
  • A_Idle_HorseRiding
  • AM_Buggy_MountLeft
  • AM_Buggy_MountRight
  • AM_Buggy_DismountLeft
  • AM_Buggy_DismountRight
  • A_Idle_BuggyDriving
  • A_Idle_BuggySeated

The “A” stand for normal Animation Sequences you can plugin to your anim graph while the AM stand for AnimMontages that can be played over your current Animations if setup properly.

Custom Animations
Fig 1.1.1 Custom Animations

All of these AnimMontages are setup to play from the Default Slot, nothing really special has been set up for them beyond that.  You will see anim notifies if you are looking at the Finished project and we will cover that later.

Robot Horse

My legendary Robot Horse!  It has no animations, and a body built of highly detailed reflective spheres and cubes, but it does the job of a stand in horse mount with a skeleton of its own.  Maybe one day I’ll add animations to it but right now I got bigger projects to build.  Currently it is programmer art at best, I highly suggest replacing it with your own mount or using one of the Epic Assets.  I have found the Bear in the Infinity Blade : Advisaries pack or even Shinbi's Wolf make great replacements.


2.0 Create the Basic Assets

Return to Table of Contents

This section will cover creating the basic foundations we will need for this tutorial.  This includes the Folder Structure as well as the Blueprint Assets we will be using.

Project Folder Structure
Fig 2.0.1 Folder Structure

If it is not already created start by Creating the MountingContent folder. 

Then create the Blueprints Folder inside the "MountingContent" folder

Finally create the Maps Folder also in the "MountingContent" folder.

Save Map
Fig 2.0.2 Save Map

If you do not have a MountingMap already, create it by opening the ThirdPersonExampleMap found under “Content/ThirdPersonBP/Maps” and then select SaveAs. 

Save the map under “Content/MountingContent/Maps” as “MountingDemoMap”

Create New Character
Fig 2.0.3 Create New Character

Next go to “MountingContent/Blueprints” and create a new Blueprint Class.

Choose the ThirdPersonCharacter as the base class and name it “BP_MountingCharacter”.  We’ll use the ThirdPersonCharacter as a starting point for our own character because it is already setup for basic movement and a camera.

Create Mount
Fig 2.0.4 Create Mount

Next Duplicate “BP_MountingCharacter” or create another Blueprint Class from the ThirdPersonCharacter and name it “BP_Horse”. This will be our horse to mount.  Alternatively you can use the Buggy from the Advanced Vehicle Content Package.

Setup Horse Mount Basics
Fig 2.0.5 Setup Horse Mount

Open up the “BP_Horse” and select the Mesh Component. 

Set the Mesh of the Mesh component to be “RobotHorse_01”. 

Then Set the “Anim Class” to “ABP_RobotHorse_C”.  This AnimBlueprint currently does nothing interesting but is a placeholder for the future when I decide to add a bit more to the Robot Horse.

Create New Controller
Fig 2.0.6 Create New Controller

Next Create a new Blueprint Class using the “PlayerController” as a base class.

Name the new Player Controller “BP_MountingPlayerController”.

Create new Game Mode
Fig 2.0.7 New Game Mode

Finally create another new blueprint using the "GameModeBase" as the base class.  We will be using it for playing the game. 

Call the new GameMode class “BP_MountingGameMode”.

Setup Game Mode
Fig 2.0.8 Setup Game Mode

Open up the newly created game mode and set “BP_MountingPlayerController” for the “Player Controller Class”. 

Then set “BP_MountingCharacter” for the “Default Pawn Class”.

World Settings
Fig 2.0.9 World Settings

Finally with the “MountingDemoMap” open go to World Settings. You may need to activate this pane by going to “Window->WorldSettings”. 

In the GameMode section choose “BP_MountingGameMode” from the dropdown menu.


3.0 Interface and Component Setup

Return to Table of Contents

In this section we will be adding the required Interfaces and Components to each of the assets we have created.

Add Character Interfaces
Fig 3.0.1 Add Character Interfaces

Click on Class Settings at the top of the Blueprint. 

Under the Interface Section in the Details Panel click the “Add” Drop down. 

Add the “ADMUnifiedControllerPawn” interface. 

Then Add the “MountRiderInterface”.  We will go over what each of these interfaces do in the next section.

Add Rider Component
Fig 3.0.2 Add Rider Component

Next add the “Mount Rider Component" to the component’s window of the BP_MountingCharacter class. 

For the purposes of this tutorial name it "MountRiderComponent".  That is all we will do for now, the next sections will cover implementing the interfaces with the components.

Add Mount Interface
Fig 3.0.3 Add Mount Interface

Open up the “BP_Horse” blueprint. 

Select “Class Setting” from the Top Menu and then in the “Details” Panel under the Interfaces panel click the “Add” drop down. 

Add the “ADMUnifiedControllerPawn”. 

Then Add the “MountablePawnInterface”.

Add Mount Component
Fig 3.0.4 Add Mountable Component

Next add the “Mountable Pawn Component” to the component’s window of the BP_Horse. 

For this tutorial name it "MountablePawnComponent".

Make sure you check the property "Is Mountable" to true.  This will be used to toggle mounting ability on or off for the entire blueprint class.

This is all we will do for now as the next sections cover implementing these interfaces with the components.

Add Controller Interfaces
Fig 3.0.5 Add Controller Interfaces

Open the “BP_MountingPlayerController” blueprint.

Select “Class Settings” from the top menu and then in the “Details” Panel under “Interfaces” click the “Add” Drop down. 

Add the “ADMUnifiedControllerPawn” interface. 

Then add the “RiderControllerInterface” interface. 

Add Controller Component
Fig 3.0.6 Add Controller Component

Next add the “Mount Rider Controller Component” to the component’s window of the BP_MountingPlayerController”. 

Name it "RiderControllerComponent". 

The next sections will cover implementing the interfaces with these components


4.0 Setup PlayerController

Return to Table of Contents

This section we will go over the easiest system to implement, the controller.  In a later tutorial we will go over developing a basic interaction system for you to use with the controller.  The mounting system does not implement an interaction system natively and relies on your own expertise and project requirements to do this.  However triggering the mounting and dismounting system is easy with a single function you can call for each of these operations.

4.1 General Setup

We will first go through setting up some basic properties and functions.

4.1.1 Setup the Owned Pawn

Enable RPCs
4.1.1.1 Enable Rpcs

In the "Components" Panel select the "RiderControllerComponent" from the list.

Then in the "Details Panel" check true the property "Enable Action Rpcs".  This option will allow the RiderControllerComponent to automatically send RPC calls rather than having to define your own on the character.  RPC functions on components have a slight network overhead which is why this is an optional setting, with out this turned on you would need to first check if you are running on the Server or the Client and setup your own RPC calls to send the request between the two.  Older versions of the PNMS did not have RPCs setup at all and you needed to create them manually in the blueprint or code, now you have the option.  It is important to note that the overhead is relatively small and because these functions are not being fired on tick (like the movement components are) the overhead is negligible.

Override On Possess
4.1.1.2 Override On Possess

Next we will setup possession logic that tell the PNMS who our owned pawn is and who our controlled pawn is.  You do this with a single funciton call from the RiderControllerComponent called "SetControlledPawn".  You can learn more about owned and controlled pawns from the Concepts tutorial.

In the Functions hover over it until you see the “Override” option appear. 

Click the “Override” option and search for “OnPossess”. 

This function is fired every time the controller takes possession of any pawn. 

On Possess
Fig 4.1.1.3 On Possess

Get the RiderControllerComponent and call it’s function “SetControlledPawn”. 

Pass in the “PossessedPawn” parameter to the “newControlledPawn” function parameter.

This is very important for ensuring the mounting system works properly.  See Concepts for more information about Controlled vs Owned Pawns.

4.2 Unified Controller Pawn Interface

Return to Table of Contents

4.2.1 Prepare to Mount

Prepare To Mount
Fig 4.2.1.1 Prepare To Mount

This is one of the preparatory function that will be called during the mounting process.  In previous versions of the mounting system this interface function was used to start the mounting process but as of version 2.2 that responsibility has been off loaded to a different function.  We will call this function manually in the "BeginMountingActor" and "BeginMountingActorToSeat" functions later when we implement the IRiderController interface in the next section.  In post 4.26 engine versions this function will be automatically called.  We do it this way because we do not want to break current implementations on unreal engine versions 4.25 and 4.26.

Implement prepare to mount by simply returning true.  Ideally this is where you would add logic that could stop the mounting process before it begins or where you can add some custom logic that occurs before mounting begins.

4.2.2 Prepare to Dismount

Prepare To Dismount
Fig 4.2.2.1 Prepare To Dismount

This is one of the preparatory functions that is called during the dismounting process.  In previous versions of the mounting system this interface function was used to start the dismounting process but as of version 2.2 that responsibility has been moved to a different function.  We will call this function manually in the "BeginDismountingActor" function later when we implement the IRiderController Interface in the next section.  In post 4.26 engine versions this funciton will be automatically called.  We do this so that we do not break the implementations of current mounting systems on engine versions of 4.25 and 4.26.

We implement this function by simply returning true.  Ideally this is where you would add logic that could stop the dismounting process before it begins or where you can add some custom logic that occurs before mounting begins.  As an example you may not want players to dismount while in a cutscene or while traversing on certain mount that automatically travel to the desired location.

4.2.3 Is Mounted

This function can be used to test of your character is currently mounted.

Is Mounted
Fig 4.2.3.1 Is Mounted

Implement Is Mounted by calling the “IsMounted” function from the “RiderControllerComponent”

4.2.4 Get Character Pawn

This function can be used to get your original pawn.  This is useful in many situations where you maybe unsure if you are using the Mount or the Character, particularly in UI and Collisions events.

Get Character Pawn
Fig 4.2.4.1 Get Character Pawn

Implement “GetCharacterPawn” by calling “GetOwnedPawn” from the RiderControllerComponent.

4.2.5 Get Character Mount

This funciton can be used to get the current mount.  If the character is not mounted it will simply return null (None)

Get Mount
Fig 4.2.5.1 Get Mount

Implement “GetCharacterMount” by calling “GetMountActor” from the RiderControllerComponent

4.2.6 Get Character Controller

This function is used to get the Controller.  This is most useful in situations where you may need the controller but only have reference to an Actor such as in collision events.

Get Controller
Fig 4.2.6.1 Get Controller

Implement “GetCharacterController” by supplying Self.  As noted one of the purposes of this interface is in situations where you do not fully know the implementation of a system are using or have designed your system to leverage a different type of object.  

4.3 Implement IRiderControllerInterface

Return to Table of Contents

4.3.1 Possess Pawn (PNMS)

This function is called by the mounting and dismounting process to trigger the possession of the Mount or the repossession of the Rider.

Possess Character
Fig 4.3.1.1 Possess Pawn (PNMS)

We implement this function by dragging a "RiderControllerComponent" get node onto the graph.

Then draw a line from the "RiderControllerComponent" node and search for "PossessPawn" and add the function node to the graph.

Feed the "PawnToPossess" input paraemter from the "PossessPawn" function node into the "PossessPawn" function of the "RiderControllerComponent".

Connect the return value of "PossessPawn" to the return vlaue node.

4.3.2 OnRiderAdded

This function is called from the Mount when ever a rider is added to a seat.  It's main purpose is to alert all seated riders that a new rider has joined the mount.  You can leverage this to update your UI to indicate available and unavailable seats.

On Rider Added
Fig 4.3.2.1 On Rider Added

You implement this function by dragging a get node for "Rider Controller Component" onto the graph.

Then draw a line from "RiderControllerComponent" node and look for "RiderAdded" function.

Connect the input parameter "New Rider" to the input parameter of the "RiderAdded" funciton of the same name.

Connect the input parameter "Seat Id" to the input parameter of the "RiderAdded" function of the same name.

Return true.

Component Delegates
Fig 4.3.2.2 Component Delegates

Implementing this interface function allows you to implement the "OnRiderAdded" delegate function of the "RiderControllerComponent".

4.3.3 OnRiderRemoved

This function is called from the Mount when ever a rider is removed from a seat.  It's main purpose is to alert all seated riders that a rider has left the mount.  You can leverage this to update your UI to indicate available and unavailable seats.

On Rider Removed
Fig 4.3.3.1 On Rider Removed

You implement this function by dragging a get node for "Rider Controller Component" onto the graph.

Then draw a line from "RiderControllerComponent" node and look for "RiderRemoved" function.

Connect the input parameter "Removed Rider" to the input parameter of the "RiderRemoved" funciton of the same name.

Connect the input parameter "Seat Id" to the input parameter of the "RiderRemoved" function of the same name.

Return true.

4.3.4 OnOtherRiderChangedSeat

This function is called from the Mount when ever a rider changes seats.  It's main purpose is to alert all seated riders that a rider has moved to a new seat.  You can leverage this to update your UI to indicate available and unavailable seats.

On Other Rider Changed Seats
Fig 4.3.4.1 On Other Rider Changed Seats

To implement this function drag a get node for "Rider Controller Component" onto the graph.

Then draw a line from "RiderControllerComponent" node and look for "OtherRiderChangedSeat" function and add it to the graph.

Connect the input parameter "Other Rider" to the input parameter of the "OtherRiderChangedSeat" funciton of the same name.

Connect the input parameter "New Seat Id" to the input parameter of the "OtherRiderChangedSeat" function of the same name.

Connect the input parameter "Old Seat Id" to the input parameter of the "OtherRiderChangedSeat" function of the same name.

Return true.

4.3.5 OnMountActionFailed

Called when an error occurs within the mounting system during the mounting phase.

On Mount Action Failed
Fig 4.3.5.1 On Mount Action Failed

 As of 4.25 this function is called whenever an attempt to mount fails.  A log will also accompany this failure and you can use the FMountActionResponse structure to find out what caused the failure. All Prepare and Start interface functions return the response structure so you can customize reasons for why you failed the mounting in your game to send the player messages appropriately.

4.3.6 OnDismountActionFailed

Called when an error occurs within the mounting system during the dismounting phase.

On Dismount Action Failed
Fig 4.3.6.1 On Dismount Action Failed

As of 4.25 this function is called whenever an attempt to dismount fails. A Log will also accompany this failure and you can use the FMountActionResposne structure to find out what caused the failure.  All Prepare and Start interface functions return a response structure so you can customize the reasons for why you failed the dismounting in your game to send the player messages appropriately.  This could be they are in the middle of a cutscene or a special event.

4.3.7 OnChangeSeatActionFailed

Called when an error occurs within the mounting system during a seat change event.

On Changed Seat Action Failed
Fig 4.3.7.1 On Changed Seat Action Failed

As of 4.25 this function is called whenever an attempt to change seats fails.  A Log will also accompany this failure and you can use the FMountActionResponse structure to find out what caused the change seat failure.  All ChangeSeat Functions return this response structure so you can customize the reasons why you failed the change seat in your game as well as handle the standard failures by the system.

4.3.8 GetRiderControllerComponent

This is a very handy function you can leverage to retrieve the RiderControllerComponent.  When combined with the IADMUnifiedPawnController it allows you to easily perform custom logic from anywhere such as collision events and within the UI widgets.

Get Controller Component
Fig 4.3.8.1 Get Controller Component

Simply return the RiderControllerComponent.  This function allows you to retrieve the RiderControllerComponent without executing a specific cast.

4.3.9 Begin Mounting Actor

This funciton is used to Start the mounting process.  This funciton acts as a wrapper for the "RiderControllerComponent" function "Perform Mount Actor" that starts position based mounting.  This means the character will mount to a seat on the mount that they are closest to.

Begin Mounting Actor
Fig 4.3.9.1 Begin Mounting Actor

To implement this funciton drag a get node for "RiderControllerComponent" onto the graph.

Draw a line from "RiderControllerComponent" and search for the function "PerformMountActor" and place it onto the graph.

Connect the execution lines from the function start node and the return node.

Draw a line or get the input parameter "New Mount" and connect it to the "New Mount Actor" input parameter for the "Perform Mount Actor" node.

Draw a line or get the input parameter "Linked Actor" and connect it to the "New Linked Actor" input parameter for the "Perform Mount Actor" node.

Now return the output parameters of "Perform Mount Actor" to the return node.

4.3.10 Begin Mounting Actor To Seat

This funciton is used to Start the mounting process to a specific seat.  This funciton acts as a wrapper for the "RiderControllerComponent" function "Perform Mount Actor To Seat" that starts seat based mounting.  This means the character will mount to a specified seat on the mount.

Begin Mounting Actor To Seat
Fig 4.3.9.1 Begin Mounting Actor To Seat

To implement this funciton drag a get node for "RiderControllerComponent" onto the graph.

Draw a line from "RiderControllerComponent" and search for the function "PerformMountActorToSeat" and place it onto the graph.

Connect the execution lines from the function start node and the return node.

Draw a line or get the input parameter "New Mount" and connect it to the "New Mount Actor" input parameter for the "Perform Mount Actor To Seat" node.

Draw a line or get the input parameter "Linked Actor" and connect it to the "New Linked Actor" input parameter for the "Perform Mount Actor To Seat" node.

Draw a line or get the input parameter "Seat Id" and connect it to the "Seat Id" input parameter for the "Perform Mount Actor To Seat" node.

Now return the output parameters of "Perform Mount Actor" to the return node.

4.3.11 Begin Dismounting Actor

This funciton is used to Start the dismounting process.  This funciton acts as a wrapper for the "RiderControllerComponent" function "Perform Dismount Actor" that starts dismounting.

Begin Dismounting Actor
Fig 4.3.11.1 Begin Dismounting Actor

To implement this funciton drag a get node for "RiderControllerComponent" onto the graph.

Draw a line from "RiderControllerComponent" and search for the function "Perform Dismount Actor" and place it onto the graph.

Then Draw a second line from "RiderControllerComponent" and search for the function "Get Mount Actor" and place it onto the graph.

Connect the output from "Get Mount Actor" to the input parameter "DismountingActor" of the "Perform Dismount Actor" node.

Connect the execution lines from the function start node and the return node.

Now return the output parameters of "Perform Dismount Actor" to the return node.

4.3.12 Begin Changing Seat to Index

This funciton is used to Start the seat changing process.  This funciton acts as a wrapper for the "RiderControllerComponent" function "Perform Change Seat To Index" that starts changing seats to a specified seat index.  The seat Index should be a valid index in the seat array of the Mount, but error handeling makes this function very forgiving.

Begin Changing Seat To Index
Fig 4.3.9.1 Begin Changing Seat To Index

To implement this funciton drag a get node for "RiderControllerComponent" onto the graph.

Draw a line from "RiderControllerComponent" and search for the function "Peform Change Seat To Index" and place it onto the graph.

Draw a line or get the input parameter "Seat Index" and connect it to the "Seat Index" input parameter for the "Perform Change Seat To Index" node.

Connect the execution lines from the function start node and the return node.

Now return the output parameters of "Perform Change Seat To Index" to the return node.

4.3.13 Begin Changing Seat By Id

This funciton is used to Start the seat changing process.  This funciton acts as a wrapper for the "RiderControllerComponent" function "Perform Change Seat By Id" that starts changing seats to a specified seat Id.  The seat Id should be a valid seat Id found on a seat in the seat array of the Mount, but error handeling makes this function very forgiving.

[IMAGE: BeginChangingSeatById]

Begin Changing Seat By Id
Fig 4.3.9.1 Begin Changing Seat By Id

To implement this funciton drag a get node for "RiderControllerComponent" onto the graph.

Draw a line from "RiderControllerComponent" and search for the function "Peform Change Seat By Id" and place it onto the graph.

Draw a line or get the input parameter "Seat Index" and connect it to the "Seat Index" input parameter for the "Perform Change Seat By Id" node.

Connect the execution lines from the function start node and the return node.

Now return the output parameters of "Perform Change Seat By Id" to the return node.


5.0 Setup the Rider

Return to Table of Contents

This section we will get to the important details of implementing the BP_MountingCharacter so it can perform the Mounting.

5.1 General Setup

First we need to setup a few important properties and settings before implementing the interfaces.

Relative Location and Rotation
Fig 5.1.1 Relative Location and Rotation

Select the "MountRiderComponent" in the "Components" panel.

On the Details Panel for the "MountRiderComponent" look for the two properties "RelativeMeshLocation" and "RelativeMeshRotation".

These two values need to match the Mesh Component's location and rotation on your character.

Mesh Details
Fig 5.1.2 Mesh Details

In multiplayer games attachment and detachment can do strange things to the local offset of the characters mesh and capsule.  These two properties are used to reset the client side mesh component when it gets off of the mount during dismounting.  In general if you are using the standard Mannequin then these values will be simple with a Z value of -90 and a Z rotation (or Yaw) of -90 degrees.  In the image above you can see where to find these values

Optional Constructor Setup
Fig 5.1.3 Optional Constructor Setup

You can use the constructor script to keep the relative locations and rotations of your mount synced up for all subclasses of your character.

Behavior Settings
Fig 5.1.4 Behavior Settings

The other thing to be aware of are the two properties “Mounting Possession Behavior” and “Dismounting Possession Behavior” these properties tell the mounting system when to take possession of the mount or the rider during the mounting and dismounting processes.  For most cases you will not need to change these values unless you are trying to achieve a specific flow.

They each have a few enum values.  For "Mounting Possession Behavior" you have the following options

  • Manual - You will handle possession of the mount in code by calling "AllowControllerToPossessMount"
  • Rider Finished Moving - Possess the mount after the rider has finished moving into position, if no movement logic is in place then it will automatically possess the mount
  • Rider Finished Mounting - Possess the mount after the mounting animation is finished playing, if no animaiton logic is in place then it will automatically possess the mount.

The "Dismounting Possession Behavior" has the following options

  • Manual - You will handle possession of the Rider in code by calling "AllowControllerToPossessRider"
  • Immedately - possess the rider immedately after triggering the dismount
  • RiderFinishedDismounting - possess the rider after the dismount animation finishes playing, if no dismount animaiton plays then the possession of the rider is immedate.
Attachment Settings
Fig 5.1.5 Attachment Settings

Next the two rider attachment behaviors tell the mounting system when it should attach the the rider to the mount and detach the rider from the mount during the mounting and dismounting process.  The two properties that control this are "Mounting Attachment Behavior" and "Dismounting Attachment Behavior".  For most cases you will not need to change these values unless you are tyring to achieve a specific effect during animation.  The values for these enums are identical to the possession values becuase they often occur nearly at the same time.

"Mounting Attachment Behavior" you have the following options

  • Manual - You will handle attachment of the mount in code by calling "AttachRiderToMount"
  • Rider Finished Moving - Attach to the mount after the rider has finished moving into position, if no movement logic is in place then it will automatically attach to the mount
  • Rider Finished Mounting - Attach to the mount after the mounting animation is finished playing, if no animaiton logic is in place then it will automatically attach to the mount.

The "Dismounting Attachment Behavior" has the following options

  • Manual - You will handle dettachment from the mount in code by calling "DetachRiderFromMount"
  • Immedately - detach the rider immedately after triggering the dismount
  • RiderFinishedDismounting - detach the rider after the dismount animation finishes playing, if no dismount animaiton plays then the detachment of the rider is immedate.

5.2 Character Unified Controller Pawn

Return to Table of Contents

5.2.1 Prepare to Mount

This function is called during the initial mounting process to prepare the character for mounting and allow it to reject the mounting and prevent it from occuring.

Prepare To Mount
Fig 5.2.1.1 Prepare To Mount

For this tutorial this function will simply return true, signaling to the mounting system that the character is prepared to start the mounting process.  However this is one of the key locations where you can inject your own logic.  This function supplies the “Mount or Rider” parameter, in the context of the character it is always going to be the mount you are attempting to get on.  If a Linked actor has been passed to the controller it will also have a value here.

Returning false for this function will abort the mounting process and prevent mounting from starting.  There could be many reasons you would not want  the player to start mounting, from them being in a special interactive scene to them not having the proper progress requirement for your game (such as a key, license, quest, achievement, etc).  Here you can also customize the response object to return any error you want using  a “Custom” code of your own.

5.2.2 Prepare to Dismount

This function is called during the initial dismounting process to prepare the character for dismounting and allow it to reject the dismounting and prevent it from occuring.

Prepare To Dismount
Fig 5.2.2.1 Prepare To Dismount

For this tutorial this function will simply return true, signaling to the mounting system that the character is prepared to start the dismounting process.  This is one of the key locations where you can inject your own logic.  This function supplies a “Mount Or Rider” parameter, in the context of the character it is always going to be the mount you are attempting to get off.

Returning false for this function will abort the dismounting process and prevent the dismounting from starting.  Like mounting, there could be many reasons why you would not want the player to start the dismounting process in your game. It could be they cannot dismount because of a cutscene or are on a special vehicle that must reach its destination first.  Here you can also customize the response object to return any error you want using  a “Custom” code of your own.

5.2.3 Is Mounted

This function allows you to retrieve a flag indicating that this character is currently mounted.

Is Mounted
Fig 5.2.3.1 Is Mounted

Implement the “IsMounted” function by using a validated get to retrieve the MountRiderComponent. 

For the IsValid execution line call the IsMounted function from the MountRiderComponent and supply it into the return. 

For the “Is Not Valid” execution line simply return false. 

Because this function could be called from the AnimBlueprint of your character you want to ensure that the MountRiderComponent has not been destroyed while the Animation Graph is updating.  This typically occurs during game shutdown where the AnimBP is still running but the components have been cleaned up and destroyed on the player.

5.2.4 Get Character Pawn

This function can be used to get your character.  This is useful in many situations where you maybe unsure if you are using the Mount or the Character, particularly in UI and Collisions events.

Get Character Pawn
Fig 5.2.4.1 Get Character Pawn

For "GetCharacterPawn" simply return self.

5.2.5 Get Character Mount

This funciton can be used to get the current mount.  If the character is not mounted it will simply return null (None)

Get Mount
5.2.5.1 Get Character Mount

For GetCharacterMount use a Validated Get for the “MountRiderComponent” 

For the IsValid execution line call the MountRiderComponent’s “GetCurrentMount” function and return it. 

For the “Is Not Valid” execution line simply return nothing.

Again the Validated Get is useful for functions that will be called by your Animation Blueprints and could be called during the game shutdown when these components may be destroyed.

5.2.6 Get Character Controller

This function is used to get the Controller.  This is most useful in situations where you may need the controller but only have reference to an Actor such as in collision events.

Get Controller
Fig 5.2.6.1 Get Controller

This is where some of the magic of the UnifiedControllerPawn interface begins to become apparent.  Calling the MountRiderComponent’s function “GetRiderController” will always return the controller that actually owns the pawn.  In cases where you are now controlling a horse or vehicle rather than your pawn this will always retrieve the Controller this character is supposed to be controlled by.

Naturally for AI Characters this will be an AI Controller but for Player Characters this will be their Player Controller.

5.3 Implement MountRiderInterface

Return to Table of Contents

This section will go over the important details of setting up a Mount or Vehicle so that it can be ridden or controlled.

5.3.1 StartPawnMounting

This function is called from the controller after it has setup all necessary references to start the mounting process for the character.

Start Pawn Mounting
Fig 5.3.1.1 Start Pawn Mounting

Implement this function by grabbing the MountRiderComponent then call it’s “MountPawn” function.

Supplying the “newPawnMount” as a parameter and returning the response and bool value.

The NewPawnMount parameter is the new pawn or actor you wish to mount.  Similar to PrepareToMount if a linked actor was supplied by the Controller it will pass it along into this function and the MountRiderComponent will skip most of the mounting logic provided the linked actor is not already occupied.

This function is called as part of the RiderControllerComponent’s “PerformMountPawn” process, if all Prepare functions return true than the last thing it calls is StartPawnMounting and the MountRiderComponent’s “MountPawn” function begins the mounting process for the character. 

As a sort of special note, The RiderControllerComponent’s “PerformMountPawn” is the start of the whole mounting process and must be called first.  It is how the Controller itself obtains and maintains a reference to the mount and your character.

5.3.2 StartPawnDismounting

This function is called from the controller after it has setup all necessary references to start the dismounting process for the character.

Start Pawn Dismounting
Fig 5.3.2.1 Start Pawn Dismounting

Implement this function by grabbing the MountRiderComponent and calling it’s “DismountPawn” function. 

Supply the “OldPawnMount” as a parameter to the function and return the output. 

Note that this function does not have an optional Linked actor input.  The mounting system is designed to treat linked actors as an intrinsic part of the overall mount itself and internally manage the connections between mount and linked actors.  That does not, however, prevent you from injecting logic into the various interface functions and obtain the linked pawn from the RiderControllerComponent or the MountRiderComponent which both have a reference to the linked actor.

OnMountingPawnFinished

This function finalizes the mounting process and must be called otherwise the mounting process will remain incomplete.  If you are using a Simple Flow (with no movement and animation) or a Mixed Flow with only Movement then this will be called automatically.  But if you are using animations then you must call this function some how to finish the mounting.  The easiest method is to use the Animation Notify "MountingFinished" which comes with the PNMS plugin.

On Mounting Pawn Finished
Fig 5.3.3.1 On Mounting Pawn Finished

Implementing this function is straight forward.  Drop a get node for "Mount Rider Component".

Draw a line from the "Mount Rider Component" node and look for the function "Pawn Finished Mounting".

Connect the output value of the "Pawn Finished Mounting" function to the return node.

This function contains a input parameter that will hold the mount being mounted to, this is optional for you to easily perform checks or other operations on the mount without having to fetch it from the component.

For more on Animations see one of the Animations Tutorial.

5.3.4 OnDismountPawnFinished

This function finalizes the dismounting process and must be called otherwise the dismounting process will remain incomplete.  If you are using a Simple Flow (with no movement and animation) or a Mixed Flow with only Movement then this will be called automatically.  But if you are using animations then you must call this function some how to finish the dismounting.  The easiest method is to use the Animation Notify "DismountFinished" which comes with the PNMS plugin.

On Dismount Pawn Finished
Fig 5.3.4.1 On Dismount Pawn Finished

To Implement this function drop a get node for "Mount Rider Component".

Draw a line from the "Mount Rider Component" node and look for the function "Pawn Finished Dismounting".

Connect the output value of the "Pawn Finished dismounting" function to the return node.

This function contains a input parameter that will hold the mount being mounted to, this is optional for you to easily perform checks or other operations on the mount without having to fetch it from the component.

In this we call "Stop Anim Montage" with no montage supplied to stop. This will cause all currently playing montages to stop running.  This may or may not be a desired effect for you, so you may need to make adjustments to store the currently running anim montage for reference later.

For more on Animations see one of the Animations Tutorial.

5.3.5 On Change To New Seat Completed

This function finalizes the seat changing process and must be called otherwise the seat changing process will remain incomplete.  If you are using a Simple Flow (with no movement and animation) or a Mixed Flow with only Movement then this will be called automatically.  But if you are using animations then you must call this function some how to finish the seat changing.  The easiest method is to use the Animation Notify "ChangeSeatsFinished" which comes with the PNMS plugin.

Change to New Seat Completed
Fig 5.3.5.1 Change to New Seat Completed

To Implement this function drop a get node for "Mount Rider Component".

Draw a line from the "Mount Rider Component" node and look for the function "Pawn Finished Changing Seats".

Connect the output value of the "Pawn Finished Changing Seats" function to the return node.

In this we call "Stop Anim Montage" with no montage supplied to stop. This will cause all currently playing montages to stop running.  This may or may not be a desired effect for you, so you may need to make adjustments to store the currently running anim montage for reference later.

For more on Animations see one of the Animations Tutorial.

5.3.6 MoveToMountingLocation

This function is called to start the character moving into the desired position for mounting.  The Location of the position and the orientation are supplied in input parameters.

Move to Mounting Location
Fig 5.3.6 Move to Mounting Location

For now we will leave the implemetnation of this function empty, returning false and skipping the movement logic entirely. 

We will cover moving in another tutorial.

5.3.7 On Move To Mounting Location Completed

When performing a move for mounting this funciton must be called to indicate that movement has completed.  When using the Simple Flow (no movement or animation) this function is called automatically.

Move to Mounting Location Complete
Fig 5.3.7 Move to Mounting Location Complete

Implementing this function is simple.  Drop a get node for "Mount Rider Component' onto the graph.

Draw a line from "Mount Rider Component" and search for "MoveToMountingLocationComplete".

Connect the output from the "MoveToMountingLocationComplete" node to the return node.

5.3.8 IsSeatedOnMount

This function can be used to determine if the character is currently sitting on the mount.  The IsSeated property of the "MountRiderComponent" is set to true once "PawnFinishedMounting" is executed.

Is Seated On Mount
Fig 5.3.8 Is Seated On Mount

To implement this function we place a get node for "MountRiderComponent" and then convert it to a Validated Get. 

Connect the "IsValid" execution line to the return.

From “MountRiderComponent” call the function “IsSeated”. 

Connect the output of the "IsSeated" funciton to the Return node connected to the "IsValid" execution line.

Add a second Return node and conect it to the "IsNotValid" execution line.

Make sure the second return node returns false.

We use a Validated Get here because this function will most likely be used by the Animation Graph.  When your game shuts down the components are destroyed first on your actor and the Animation Graph continues to update animations.  Without the validated git it will cause annoying error messages.

5.3.9 IsDriver

Is Driver
Fig 5.3.9.1 Is Driver

Place a get node for the the MountRiderComponent on the graph. 

Draw a line from "MountRiderComponent" get node and look for "IsDriver" and select it.

Connect the output from "IsDriver" the return node.

5.3.10 Get Rider Mesh

This function is used by the system to perform relative location and rotation corrections during the mounting and dismounting in networked games.  Because of lag, attaching can cause strange offsets to the mesh component which requires that it be reset during play.

Get Rider Mesh
Fig 5.3.10.1 Get Rider Mesh

To implement this function drop a get node for "Mesh" onto the graph and connect it to the return variable.

5.3.11 Get Mount Rider Component

You can use this function to retrieve the UMountRiderComponent from the character.  This is useful for implementing custom logic that the interfaces may not cover particularly in UI and Collision events and should provide improved performance over using a the "GetComponentByClass", "GetComponentByInterface", and "GetComponentByTag" functions.

Get Rider Component
Fig 5.3.11.1 Get Rider Component

To implement place down a get node for "MountRiderComponent"

Connec the output from the get node to the return value.

5.3.12 .Play Mounting Animation

This function is used to start playing the mounting animation if you have it setup.

Play Mounting Animation
Fig 5.3.12.1 Play Mounting Animation

For this demo we will leave this as it is, with the function returning false to indicate we have no animations to play.  This way the mounting system will skip playing animation and should automatically call "OnMountingPawnFinished".

In the final project there is a fully working demonstration of how you can supply animations per mount for your character that you are free use for your own games.

5.3.13 Play Dismounting Animation

This function is used to start playing the dismounting animation if you have it setup.

Play Dismount Animation
Fig 5.3.13.1 Play Dismount Animation

For this demo we will leave this as it is, with the function returning false to indicate we have no animations to play.  This way the mounting system will skip playing animation and should automatically call "OnDismountingPawnFinished".

In the final project there is a fully working demonstration of how you can supply animations per mount for your character that you are free to use for your own games.

5.3.14 Play Move To Seat Animation

This function is used to start playing the chagne seat animation if you have it setup.

Play Move To Seat Animation
Fig 5.3.14.1 Play Move To Seat Animation

For this demo we will leave this as it is, with the function returning false to indicate we have no animations to play.  This way the mounting system will skip playing animation and should automatically call "OnChangeToNewSeatCompleted".

In the final project there is a fully working demonstration of how you can supply animations per mount for your character that you are free to use for your own games.

5.3.15 Set Rider Collision Enabled

This function is called by the Mounting and Dismounting system to allow you to disable and enable collision elements of the rider.  This is useful to prevent strange physics behavior from occuring.  There are other methods of handeling collision issues with UE4 such as Custom Collison profiles.  Ultimately how you handle collision is up to you.

Set Rider Collision Enabled
Fig 5.3.15.1 Set Rider Collision Enabled

This function allows you to control how collision is disabled and enabled on the rider. The primary requirement for riders in our current implementation is that the Capsule Component collision be disabled to prevent the Character capsule from colliding with the mount collision components and doing crazy physics things.

The “ShouldEnable” parameter simply tells you if you need to enable collision or disable collision because this is the same function called for dismounting as well as mounting. How and in what way that collision is disabled or enabled is up to you.

I have chosen to Disable to Collision on the Capsule Component and use a Select Node with “No Collision” when false and “Collision Enabled (Query and Physics)” when true. In general individual mesh collision does not need to be disabled. I simply return true if successful.

5.3.16 GetSeatId

This function is used internally to fetch the current SeatID of the character as well as can be leveraged by any supporting systems you may design for the plugin.

Is Driver
Fig 5.3.16.1 Get Seat Id

To implement this we get the MountRiderComponent and drop it onto the function graph.

Then right click on the get and convert it to a "Validated Get".

From the validated get return value draw a line and search for "GetSeatId" and select it.

From the "IsValid" execution path connect it to a return node and return the value of "GetSeatId" function node.

Then from the "is Not Valid" execution line connect it to a return node which returns "0"

5.3.17 Get All Rider Skeletal Meshes

This function is used to retrieve the skeletal meshes for the character.  This function is used by the system to ensure that animations continue to play on the server even while movement replication is deactivated.  If you have linked the animations of mulitple skeletal components then you should only require the master skeletal mesh component that controls the others.

There is strange issue with Unreal Engine when you disable replicated movement on a character that seems to prevent all skeletal mesh animation updates from occurring on the server, this is fine for a dedicated server but not so fine for a Listen Server where you will see the other characters not animating. This simply facilitates the logic built into the Mounting System that ensures all Skeletal Mesh Components continue to animation after Replicate Movement is turned off on them.

Get all Rider Skeletal Meshes
Fig 5.3.17.1 Get all Rider Skeletal Meshes

To implement this function we draw a line out from the return value and search for "Make Array".

then we place a get node for "Mesh" and connect it to the element 0 of the make array node.


6.0 Implement the Mount

Return to Table of Contents

This section we will get to the important details of implementing the Mount or Vehicle so it can act as a mount for Riders.

6.1 General Setup

First we will do some basic setup for our mount.  For blueprints that have UVehicle as the parent these next steps are not required, only blueprints who are child classes of the ACharacter or whose parents are child classes of ACharacter. 

Because the mount in our tutorial is a child of ACharacter we will need to make a few small additions to it so that the movement component gets cleared when you dismount while the horse is moving.  Not doing this will result in your mount continuing to move forward on connected clients even though they are staying still on the server.

Set AIController Reference
Fig 6.1.1 Set AIController Reference

First we need to create a new variable to hold a reference to the original AIController that will take control of our mount. 

Create a new variabvle in the Variables list and call it "AIControllerRef" and make it the type "Controller".  We only need the Possess function that all controllers have so we do not care if it is a PlayerController or an AI Controller.

Search for Possessed
Fig 6.1.2 Search for Possessed

Go to the Functions section on the right side of your blueprint and hover over until you see the "Override" drop down appear. 

Click on the "Override" button and search for "Possessed" to find the Possessed Event function and click on it to start implementing it.

Override Possessed
Fig 6.1.3 Override Possessed

The Possess function passes in a "New Controller" variable.  We are indeed making an assumption that for this pawn it will always first be possessed by an AIController first and that will be the that we set to our parameter "AIControllerRef". 

I've not had any issues with this funciton not having an Authority switch as I do not believe it is executed on the client, but I still put a HasAuthority switch just in case. 

Then we first test if our AIControllerRef variable is valid by using a validated get.  If it is valid we have no need to set our reference to the controller.

That's all for our general setup here.  We'll come back to this AI controller later as we setup the MountablePawnInterface.

6.2 Unified Controller Pawn

Return to Table of Contents

This section covers implementing the ADMUnifiedControllerPawn interface for the mount

6.2.1 Prepare to Mount

This function is called during the initial mounting process to prepare the mount for mounting between the rider and the mount.  It allows the mount to reject the mounting and prevent it from occuring.  The Mount has many additional functions that can be used to peform validation checks that can be called here to test if the mount and the rider are compatible. 

For instance your rider may need to be the mount's owner, requiring them to have a key or be it's master, or be in the same party oas the owner.  Such logic is independent of the PNMS plugin and is up to your own design of your game.

Prepare To Mount
Fig 6.2.1.1 Prepare To Mount

For this tutorial this function will simply return true, signaling to the mounting system that the mount or vehicle is prepared to be mounted.  This function supplies the “Mount or Rider” parameter, in the context of a mount or vehicle it is always going to be the potential rider attempting to get on.  If the rider has tried to interact directly with a linked actor it will be passed along into the “Linked Actor” parameter.

Returning false for this function will abort the mounting process and prevent mounting from starting.  There could be many reasons you would not want the player to start mounting, for example the animal may not be tame or you may require that only the owner of the animal or vehicle can take control or get on it, or the vehicle may be broken or the animal may have been killed.

6.2.2 Prepare to Dismount

This function is called during the initial dismounting process to prepare the rider for dismounting and allow it to reject the dismounting and prevent it from ocuring.

Prepare to Dismount
Fig 6.2.2.1 Prepare to Dismount

 

For this tutorial this function will simply return true, signaling to the mounting system that the mount is prepared for dismounting.  This is one of the key locations where you can inject your own logic.  This function supplies a “Mount Or Rider” parameter, in the context of the mount it is always going to be the character attempting to get off.

Returning false for this function will abort the dismounting process and prevent the dismounting from starting.  Like mounting, there could be many reasons why you would not want the player to start the dismounting process in your game. It could be that they are in a cutscene or traveling too fast to get off or that the mount has not reached its destination yet.

6.2.3 Is Mounted

This function allows you to retrieve a flag indicating that this mount has at least one rider.

Is Mounted
Fig 6.2.3.1 Is Mounted

To Implement this function, place a get reference to the "MountablePawnComponent".

Draw a line from "MountablePawnComponent" node and search for the function “IsMounted”.

Return the output of "IsMounted" by connecting it to the return node.

6.2.4 Get Character Pawn

This function can be used to get the current driver of the mount.  In the mounting system the context of the "Pawn" is always refering to the "Owned Pawn" of the current "Player Controller". 

Get Character Pawn
Fig 6.2.4.1 Get Character Pawn

To implment this funciton place down a get node for "MountablePawnComponent".

Then draw a line from the "MountablePawnComponent" node and search for "GetDriver".

return the output of "GetDriver" through the return node.

6.2.5.1 Get Character Mount

This funciton is used to get the current mount, for characters that are always mounts that will always be itself.  However for characters that maybe able to serve as both a "mount" and a rider this becomes abit more complicated.  For an example of how to setup a character that can act as both, see the example tutorials in the finished project in the "Mountable Character" demo.  It is important to note that for most mounts that are also riders, you will not want the other player to take control of them.  We will go over later how to make a character mountable but not possessable.

Get Character Mount
Fig 6.2.5.1 Get Character Mount

For characters that are mounts we simply return itself since it is the mount. Simply right click and return “Self”.

6.2.6 Get Character Controller

This function is used to get the Controller.  This is most useful in situations where you may need the controller but only have reference to an Actor such as in collision events.

Get Character Controller
Fig 6.2.6.1 Get Character Controller

For mounts we always simply return the current Controller that is controlling them.  Simply right click and search for “GetController” and return it.

6.3 Implement MountablePawnInterface

Return to Table of Contents

This section covers the implementation of the IMountablePawn Interface.

6.3.1 Must Have Driver

This function is used to determine if the mount must have a driver fill it's dirver seat first before all other seats.  This will force the position mounting system to always put new riders on the driver seat.  For implementations where the player can choose a direct seat then it is ignored if the player chooses a seat other than the driver seat.

Must Have Driver
Fig 6.3.1.1 Must Have Driver

To implement this function add a get node for "MountablePawnComponent".

Draw a line from "MountablePawnComponent" and search for the function "Must Have Driver" and select it.

Connect the output of "Must Have Driver" to the return node.

6.3.1 IsMountableActor

This function returns a flag indicating that the Mount is a mountable object.  It is not meant to indicate if the mount is capable of being mounted (such as if it has all its seats, simply that it can server as a mount).  This is one method of deactivating the mounting ability of a mount in subclasses.

Is Mountable Pawn
Fig 6.3.2.1 Is MountabountablePawnComponent le Pawn

To implement this function add a get node for the "MountablePawnComponent" on the graph.

Draw a line from the "MountablePawnComponent" and search for the function "Can Mount".

Connect the output of "Can Mount" to the return node.

6.3.3 Is Mountable By Pawn

This is one of the functions that can be called from anyway but is best leveraged by the "Prepare to Mount" interface function.  Here you can add any custom logic for your mount to check if the supplied pawn that wants to mount it is capable of mounting it.  For instance if you need a key you can search the supplied pawn's inventory for a key or other key items or check the supplied pawn is the proper owner of the mount.

This function is not called automatically but is supplied as a option for you to use in your system.

Is Mountable By Pawn
Fig 6.3.3.1 Is Mountable By Pawn

In this demonstration we will simply return true to indicate any pawn who can interact with this mount can attempt to mount it.

6.3.4 Is Driver Seat

This function is used as part of the mounting process to determine if a supplied seat data is the same seat data as the driver seat.  This is called automatically as part of the mounting process and the dismounting process.

Is Driver Seat
Fig 6.3.4.1 Is Driver Seat

To implement this funciton place down a get node for the "MountablePawnComponent".

Draw a line from the "MountablePawnComponent" and search for the function "IsDriverSeat".

Connect the input variable named "SeatData" to the input variable "Seat Data" on the "IsDriverSeat" node.

Connect the output of "IsDriverSeat" to the return node.

6.3.5 Has Driver

This function can be used to determine if the mount currently has a driver.

Has Driver Seat
Fig 6.3.5.1 Has Driver Seat

To implement add a get node for the "MountablePawnComponent".

Draw a line from the "MountablePawnComponent" node and search for "Has Driver".

Connect the output of "Has Driver" to the return node.

6.3.6 Get Relative Mount Direction

This function is mostly used by the Position based mounting to detect the relative direction between the player.  The PNMS plugin supplies several functions capable of performing a rather fast calculation to determine where the player is standing relative to the mount.  Then you also have the ability to dicate the what valid directions the mount is capable of mounting to.  For instance a horse can be mounted form a single seat on the left or right side, but a dune buggy can only be mounted from one side on each seat, and a space ship may be mountable from any direciton when outside of it, or any way you want to setup your system.

Get Relative Position To Mount
Fig 6.3.6.1 Get Relative Mount Direction

For this demonstration we will simply make the the mount return the value "Any Side".

"Any Side" is a special case that tells the Seat Manager it has no preference so long as the seat is available.

6.3.7 Get Relative Dismount Direction

This function is meant to determine what direction character should dismount from.  For many vehicles there will be only a single direction for each seat, but for something like a horse you can setup functions to determine what direction the player is looking to get off of the mount.  There is a demonstration of this working in the final project.

Get Relative Dismount Direction
Fig 6.3.7.1 Get Relative Dismount Direction

For demonstration purposes we will simply return the default or first dismounting direction for the seat.

To implement this function draw a line from the input variable "Rider" and look for the interface function "GetSeatId (Message)". 

Then place a get node for the "Mountable Pawn Component" on the graph.

Draw a line from "Mountable Pawn Component" and search for GetDefaultPositionForSeatId".

Connect the output of "GetSeatId" to the input variable "Seat Id" on the "GetDefaultPositionForSeatId" function node.

Connect the output of "GetDefaultPositionForSeatId" to the return node.

For a more comprehensive way to set this up using the direction the player is currently looking, see the Finished Project.

6.3.8 Get Mount Body

This function is used by the mounting system to get the Mount Body that the player will be attached to.  This can be either a Skeletal Mesh or a Static Mesh.  If you have linked actors to your mount you should return the mesh of the linked actor instead of the mounts if the mount and the linked actor have different meshes.

Get Mount Body
Fig 6.3.8.1 Get Mount Body

To implement this function place a get node for the "Mesh" component on the graph.

Return the output of the "Mesh" component.

Get mount body is used to determine what mesh the player should attach themselves to.  For demonstration purposes our mount only has one mesh and so we will be returning that.  The Mesh can be any Mesh including a static Mesh, the system does not care if you are using skeletal meshes or static meshes.

However if you have linked actors this is where you would set up logic to retrieve the mesh based on the seat ID indicating the linked actor you want to get the mesh for.  

6.3.9 Get Mountable Pawn Component

This function simply allows you to get the MountablePawnComponent from any mount.  Allowing you to call functions directly on it from other supporting actors or systems such as collision events or UI elements.

Get Mountable Pawn Component
Fig 6.3.9.1 Get Mountable Pawn Component

To implement add a get node for the "MountablePawnComponent" on the graph.

Connect the output of the "MountablePawnComponent" to the return value.

6.3.10 Get Max Riders

Get the max number of riders this mount can support, usually this is the same number of seats available to the mount.

Get Max Riders
Fig 6.3.10.1 Get Max Riders

To implement this function add a get node for "MountablePawnComponent" to the graph.

From the output of "MountablePawnComponent" draw a line and search for "GetNumSeats" function.

Connect the output of "GetNumSeats" to the return value of the node.

6.3.11 Get Driver

This function is used to get the current driver of the mount.

Get Driver
Fig 6.3.11.1 Get Driver

To implement this function add a get node for "MountablePawnComponent" to the graph.

Then draw a line from the "MountablePawnComponent" node and search for the function "Get Driver".

Connect the output of the "GetDriver" function to the return node.

6.3.12 Get Current Rider Count

This funciton is used to get the current number of riders on the mount.

Get Current Rider Count
Fig 6.3.12.1 Get Current Rider Count

Add a get node for the "MountablePawnComponent" to the graph.

Draw a line from the "MountablePawnComponent" and search for the function "GetNumRiders".

return the output of the "GetNumRiders" node to the return node.

6.3.13 Find Available Mounting Position

This function is primarily used when mounting using a relative position instead of a direct mount to a seat.  This funciton supplies a current location of the rider as well as their relative direction retrieved the function "GetRelativeMountDirection".  The component uses these two values to find a seat with the closest location for the player to attach to and start mounting.  If "Must Have Driver" is enabled and the mount currenlty has no driver than this function will alway return the driver seat position if it is available.

Find Available Mounting Position
Fig 6.3.13.1 Find Available Mounting Position

Place a get node for "MountablePawnComponent" onto the graph.

Draw a line from the "MountablePawnComponent" node and search for the function "Find Available Mounting Position".

Get the MountablePawnComponent and call “FindAvailableMountingPosition”. 

Pass in the “Position” enum retrieved from the “GetRelativeMountDirection” and the “RiderLocation” parameters. 

Then return the outputs.

This function's main purpose is to find the best seat available according to your current distance from the mount and relative direction from the mount.  It also performs a distance validation check so you cannot mount too far way from the mount itself.

6.3.14 Is Seat Occupied By Id

Allows you to query if a specific seat is occupied by the seats ID.

Is Seat Occupied By Id
Fig 6.3.14.1 Is Seat Occupied By Id

To Implement this function we place down a get node for the "MountablePawnComponent".

Draw a line from the "MOuntablePawnComponent" and search for the funtion "IsSeatOccupiedById".

Connect the input variable "Seat Id" to the function "Is Seat Occupied by Id" input variable called "Seat Id".

Connect the output of "IsSeatOccupiedById" to the return node.

Get the MountablePawnComponent and call it’s “IsSeatOccupiedById” function.  Pass the “Seat Id” parameter into it and return it’s value.

6.3.15 Is Seat Occupied At Index

Allows you to retrieve a flag indicating that the seat at the specified index is occupied by a rider.

Is Seat Occupied At Index
Fig 6.3.15.1 Is Seat Occupied At Index

To Implement this function place a get node for "MountablePawnComponent'.

Draw a line from "MountablePawnComponent" and search for the function "IsSeatOccupiedAtIndex".

Connect the function input variable "Seat Index" to the"IsSeatOccupiedAtIndex" function node's input parameter "Seat Index"

Connect the output from "IsSeatOccupiedAtIndex" to the return node.

6.3.16 Set Seat Occupied By Id

This function allows you to set a specific set as occupied by the unique ID of the .  Generally you will not need to directly call this function.

Set Seat Occupied By Id
Fig 6.3.16.1 Set Seat Occupied By Id

To implement this function place a get node for the "MountablePawnComponent" onto the graph.

Draw a line from the "MountablePawnComponent" and search for the funtion"SetSeatOccupiedById"

Connect the input parameter "Seat Id" to the input property "Seat Id" of the "SetSeatOccupiedById" function node.ction "SetSeatOccupiedById".

Connect the input parameter "Rider" to the input property "Rider" of the "SetSeatOccupiedById" function node.

Connect the output of "SetSeatOccupiedById" to the return node.

Get the MountablePawnComponent and call its SetSeatOccupiedById. Pass “SeatId” and “Rider” parameters into the function and return the output

6.3.17 Set Seat Occupied At Index

This function allows you to set a specific set as occupied according to it's index in the seat array.  Generally you will not need to directly call this function.

Set Seat Occupied At Index
Fig 6.3.17.1 Set Seat Occupied At Index

To implement this function place a get node for the "MountablePawnComponent" onto the graph.

Draw a line from the "MountablePawnComponent" and search for the function "SetSeatOccupiedAtIndex".

Connect the input parameter "Seat Index" to the input property "Seat Index" of the "SetSeatOccupiedAtIndex" function node

Connect the input parameter "Rider" to the input property "Rider" of the "SetSeatOccupiedAtIndex" function node.

Connect the output of "SetSeatOccupiedAtIndex" to the return node.

6.3.18 Clear Seat By Id

This function allows you to clear the reference to a rider and mark a seat as unoccupied by using the seats Id. In general there are very few instances where you will need to call this function directly.

 Clear Seat By Id
Fig 6.3.18.1 Clear Seat By Id

To Implement this function place a get node for the "MountablePawnComponent" on the graph.

Draw a line from the "MountablePawnComponent" node and search for the function "ClearSeatById"

Connect the input variable "Seat Id" to the input property "Seat Id" of the "ClearSeatById" function.

Connect the output value of "ClearSeatById" to the return node.

6.3.19 Clear Seat By Index

This function allows you to clear the reference to a rider and mark a seat as unoccupied by iby the seats index within the mounts seat array. In general there are very few instances where you will need to call this function directly.

Clear Seat At Index
Fig 6.3.19.1 Clear Seat At Index

To Implement this function place a get node for the "MountablePawnComponent" on the graph.

Draw a line from the "MountablePawnComponent" node and search for the function "ClearSeatById"

Connect the input variable "Seat Id" to the input property "Seat Id" of the "ClearSeatById" function.

Connect the output value of "ClearSeatById" to the return node.

6.3.20 Get Seat Data By Id

Get a copy of a seats data by using it's id.  This copy will include current occupying actor as well as the seats mounting and dismounting data and socket attachment.  This funciton has two return values, one containing the seat data and the other indicating a successful retrieval of the desired seat data that you can use to test if the seat data was found.

Get Seat Data By Id
Fig 6.3.20.1 Get Seat Data By Id

To implement this function place a get node for "MountablePawnComponent" on the grpah.

Draw a line from "MountablePawnComponent" and search for the function "GetSeatDDataById".

Connect the input variable "SeatId" to the input variable "Seat Id" from the "GetSeatDataById" function node.

Connect the output variable "Seat Data" to the return node output "Seat Data"

Connect the output variable "Return Value" to the return node output "Return Value".

6.3.21 Get Seat Data At Index

Get a copy of a seats data by using its index in the seat array of the mount.  This copy will include current occupying actor as well as the seats mounting and dismounting data and socket attachment.  This funciton has two return values, one containing the seat data and the other indicating a successful retrieval of the desired seat data that you can use to test if the seat data was found.

Get Seat Data At Index
Fig 6.3.21.1 Get Seat Data At Index

To implement this function place a get node for "MountablePawnComponent" on the grpah.

Draw a line from "MountablePawnComponent" and search for the function "GetSeatDDataAtIndex".

Connect the input variable "Index" to the input variable "Index" from the "GetSeatDataAtIndex" function node.

Connect the output variable "Seat Data" to the return node output "Seat Data"

Connect the output variable "Return Value" to the return node output "Return Value".

6.3.22 Can Mount Actor

This function primarily servers as a method to determine if the mount is in a mountable state.  Here you can add rules to check various proeprties of the mount.  The New Rider parameter is supplied to allow you to check if the new rider trying to mount is allowed to mount by ccalling the function "IsMountableByPawn".  This function must return true in order to mounting to proceed successfully.

Can Mount Pawn
Fig 6.3.22.1 Can Mount Actor

To implement this function we will reuse a few interface functions we have already setup.

Click anywhere on the graph and search for the function "GetMaxRiders".

Again click anywhere and search for the funvtion "GetCurrentRiderCount".

Draw a line from "GetMaxRiders" output and look for the ">" (greater then symbol) and be sure to select the "integer > integer"

Connect the output from "GetCurrentRiderCount" to the second pin of the ">" node.

This initial greater then tests allows us to determine of the mount has available seats.

Again click anywhere and look for the 'IsMountableActor" function.

Draw a line from the ">" node and search for "AND" and be sure to choose "AND Boolean"

Connect the output from the "IsMountableActor" function to the second input pin of the "AND" node.

Finally connect the output of the "AND" node to the return value of the function.

This is a crucial function that must return true for mounting to proceed.  It can be implemented in any way you deem fit but I implement it in the following way.  Get the “GetMaxRiders” interface function, the “GetCurrentRiderCount” interface function, and “IsMountableActor” interface function.  Extend the return value of “GetMaxRiders” and choose a “GreaterThan” boolean operation.  Connect “GetCurrentRiderCount” to the second input.  Then Drag off the bool pin from the “greater than” sign and connect it to an “Boolean And” operation.  Connect the IsMountableActor interface function to that.

6.3.23 Can Mount At Position

This function can be used to test if the character is able to mount at a specified location and direction.

Can Mount At Position
Fig 6.3.23.1 Can Mount At Position

To implement this function we will reuise a previous interface funciton "Find Avaialble Mounting Position".

Click on the graph and look for the function "FindAvailableMountingPosition" and add it to the graph.

Connect the "RiderLocation" input parameter to the "FindAvailableMountingPosition" functions input parameter "Rider Location"

Connect the "Desired Mounting Position" input parameter to the "Find Avaialble Mounting Position" functions input parameter "Position".

Connect the ouput node "Return Value" to the return node.

6.3.24 On Rider Finished Mounting

This function is called on the mount when ever a Rider finishes mounting. This occurs specifically when the RiderComponent calls "PawnFinishedMounting".  This allows you to add additional logic to to the mount when ever a new rider finishes mounting such as updating the UI or calling a Dispatcher function.  When implemented properly this function also sends the signal that a pawn finished mounting to all other riders on the mount allowing them to update UI elements as well.

On Rider Finished Mounting
Fig 6.2.24.1 On Rider Finished Mounting

To implement this function place a get node for the "MountablePawnComponent" on the graph.

Draw a line from the "MountablePawnComponent" and search for the function "RiderFinishedMounting".

Connect the "MountedActor" input parameter to the "RiderFinishedMounting" functions input parameter "Actor"

Connect the "SeatId" input parameter to the "RiderFinishedMounting" functions input parameter "SeatID"

On the return node check it's return value to true.

6.3.25 On Rider Finished Dismounting

This function is called on the mount whenever a Rider finishes dismounting. This occurs specifically when the RiderComponent calls "PawnFinishedDismounting".  This allows you to add additional logic to to the mount whenever a new rider finishes disounting such as updating the UI or calling a Dispatcher function.  When implemented properly this function also sends the signal that a pawn finished disounting to all other riders on the mount allowing them to update UI elements as well.

On Rider Finished Dismounting
Fig 6.3.25.1 On Rider Finished Dismounting

To implement this function place a get node for the "MountablePawnComponent" on the graph.

Draw a line from the "MountablePawnComponent" and search for the function "RiderFinishedDismounting".

Connect the "Dismounted Actor" input parameter to the "RiderFinishedDismounting" functions input parameter "Dismounted Actor"

Connect the "SeatId" input parameter to the "RiderFinishedDismounting" functions input parameter "SeatID"

You can place a get node on the graph for the input parameter "Seat Id" which may make it cleaner to look at the graph.

The next part of this function implementation is to faciliate an issue I have discussed about possessing characters where they can keep moving forward on the client while standing still on the server.  To fix this we have the previous AI Controller retake control of the mount if the driver has left.

Draw a line from the "MountablePawnComponent" and search for the function "IsDriverSeatId"

Connect the "SeatId" input parameter to the "IsDriverSeatId" functions input parameter "SeatID"

Place down a branch node and connect the execution line from "RiderFinishedDismounting" to it.

Connect the output of "IsDriverSeatId" to the "conditioon" input of the Branch node.

AI Repossession
Fig 6.3.25.2 AI Repossession

The second half of this function we will return control to the AIController we setup earlier.  If the seat we just dismounted from is the driver seat than we want to return control of the mount back over to the AI Controller to prevent “funny client side movement”

If we are dealing with a driver seat then check if we are on the authority.

If we are on the authority check if the AIControllerRef variable we setup is valid.

Now we have the Ai Controller possess the mount.

Return true for all paths.

6.3.26 On Rider Finished Changing Seats

This function is called on the mount whenever a Rider finishes changing to a new seat. This occurs specifically when the RiderComponent calls "OnCharacterChangedSeats".  This allows you to add additional logic to to the mount whenever a rider changes seats such as updating the UI or calling a Dispatcher function.  When implemented properly this function also sends the signal that a pawn finished changing seats to all other riders on the mount allowing them to update UI elements as well.

On Rider Finished Changing Seats
Fig 6.3.26.1 On Rider Finished Changing Seats

To implement this function  place down a get node for "MountablePawnComponent"

Draw a line from "MountablePawnComponent" and look for the function "RiderFinishedChangingSeats".

Connect the "Rider" input parameter to the "RiderFinishedChangingSeats" functions input parameter "Rider"

Connect the "New Seat Id" input parameter to the "RiderFinishedChangingSeats" functions input parameter "New Seat Id"

Connect the "Old Seat Id" input parameter to the "RiderFinishedChangingSeats" functions input parameter "Old Seat Id"

The next part of this function implementation is to faciliate an issue I have discussed about possessing characters where they can keep moving forward on the client while standing still on the server.  To fix this we have the previous AI Controller retake control of the mount if the driver has left.

Draw a line from the "MountablePawnComponent" and search for the function "IsDriverSeatId"

Connect the "Old Seat Id" input parameter to the "IsDriverSeatId" functions input parameter "Seat Id"

Place down a branch node and connect the execution line from "RiderFinishedChangingSeats" to it.

Connect the output of "IsDriverSeatId" to the "conditioon" input of the Branch node.

AI Repossession
Fig 6.3.26.2 AI Repossession

The second half of this function we will return control to the AIController we setup earlier.  If the seat we just dismounted from is the driver seat than we want to return control of the mount back over to the AI Controller to prevent “funny client side movement”

If we are dealing with a driver seat then check if we are on the authority.

If we are on the authority check if the AIControllerRef variable we setup is valid.

Now we have the Ai Controller possess the mount.

Return true for all paths.

6.3.27 Is Driver Ready

This function can be used to determine of the driver is ready to control the mount.  The most use of this function is determine if the player can start using input controls for the mount or not.  Another use maybe within the mounts animation blueprint in case the mount is meant to have different animations when mounted versus when unmounted.

Is Driver Ready
Fig 6.3.27.1 Is Driver Ready

Call the “GetDriver” interface function directly and check it using an “IsValid” macro.

From the IsValid execution line call the “IsSeatedOnMount” Message with the return value of “GetDriver” as it’s target.

Return the value of IsSeatedOnMount.

From the IsNotValue execution line simply return true, since there is no driver, everything is ready to go.

6.3.28 Has Passengers

This is a utility function to allow you to determine if a mount has passengers, this usually includes the driver.

Has Passengers
Fig 6.3.28.1 Has Passengers

Place down a get node for the "MountablePawnComponent".

Draw a line from the "MountablePawnComponent" and search for the function "GetNumRiders".

Draw a line from the "GetNumRiders" function and look for the ">" (Greater then symbol).

Keep the second parameter as zero.  If we have more than 0 riders then this mount has passengers.

Connect the output of the ">" node to the return value.


7.0 Setup Mount Seats

Return to Table of Contents

Now it is time to set up the Seats to your mount.  The first thing we will do is make sure we have an appropriate socket that will act as the attachment point to our mount.

7.1 Setup Sockets

Open up the mesh that will represent your vehicle or mount.  For both Skeletal Meshes or Static Meshes you will want to create a socket. 

Setup Mount Skeleton
Fig 7.1.1 Setup Mount Skeleton

For the robot horse I have defined two sockets “s_DriverSeat” and “s_PassangerSeat”  I have configured their rotation and position so that if I attach a character to them they will automatically be facing in the correct location.

The “s_DriverSeat” is attached to the “b_spline_03” bone. It has a Relative location of (X=-0.000003,Y=-9.000000,Z=13.000000) and a relative rotation of (Pitch=-34.000000,Yaw=-90.000000,Roll=0.000000).

The “s_PassangerSeat” is attached to the “b_spine_02” bone.  It has a relative location of (X=0.000000,Y=2.000000,Z=18.000000) and a relative rotation of (Pitch=0.000000,Yaw=-90.000000,Roll=0.000000).

Be aware that attempting to use the mannequin Mesh itself to orient your rider will not work for any mount because the rotation of the mannequin is -90 degrees around the Z axis (or Yaw).  So while you can set up the socket preview using the mannequin Mesh you’ll need to rotate it -90 Degrees around the Z axis (Yaw) for it to be correct.

Honestly the socket locations and rotations I have setup were all 100% trial and Error.  Because the Skeleton is an Asset type in UE4 you can actually change the socket positions and rotations and save the skeleton. Then get off and back on the mount and it will have updated the socket attachment so you can see the changes live without continuously starting and stopping Play in Editor (PIE).

7.2 Setup Seats

With the sockets defined we will now setup the available seats on the mount.  Open up the mount you want to define seats for.

Mount Component Details
Fig 7.2.0.1 Mount Component Details

Select the “MountablePawnComponent” under the Component’s window.  This should show you the details panel of the component. 

Look for the “Mounting” category and expand the “Seat Manager” property.

Seats Added to Mount
Fig 7.2.0.2 Seats Added to Mount

Within the Seat Manager this is an array called “Seats”.  Add two seats by pressing the plus sign.  We will be designating seat 0 as the driver seat and seat 1 as the passenger seat.

In the seat manager we want to ensure a few values are set for our Mount.  The “Force Driver Seat” should be checked.  This value enforces that the first seat taken should always be the driver seat.  You can disable this if you want the closest seat to the player to take priority.

Then make sure “IsPossessableMount” is enabled.  This must be set to true if you want your players to be able to drive the mount or vehicle.  You can disable this if you just want your players to take a specific seat on the mount.

“Max Valid Mounting Distance Squared” represents the maximum distance that this mount can be from the mount for it to be considered valid for attempting to start the mounting process.  Remember that this is the Squared distance.  So by default it is set to 90000 which is 300 cm or 3 meters from the mount in any direction.

Now ensure that the “Driver Seat Id” property to 0.  You should see the Driver Seat Index update as well.

7.2.1.Setup Driver Seat

Driver Seat Setup
Fig 7.2.1.1 Driver Seat Setup

Now expand element 0 of the Seats Array.  It should have a “Seat Id” of 0.  Set the “Seat Socket Name” to “s_DriverSeat”.  The MountingData property is an array that describes how the seat can be attached to.  Add Two elements to the Array and Expand it.

Set Driver Seat Position Data

Driver Seat Mounting Positions
Fig 7.2.1.2 Driver Seat Mounting Positions

Expand Element 0 of the Mounting Data array.  Set the “Mount Position” to “Left Side”.  Then set the “Relative Mounting Offset” to <30, -50, 0.0>.  This should translate to 30 units of the mounts forward direction and 50 units to the left side of the mount.

The “Relative Mounting Offset” is a vector offset from the center location of the mount. It tells the mounting system a relative position from the center of the mount that a rider needs to be located at to start mounting.  Generally this is the location provided to “MoveToMountingLocation” translated into world coordinates. 

By enabling “Use Separate Offset for Dismounting” you can set a different offset for the position to detach the character onto and place the capsule at.  Like “Relative Mounting Offset” the “Relative Dismounting Offset” is a relative location from the center of the mount actor.

On the horse we are allowing mounting to occur on both the right and left side of each seat.  So now we need to setup the Right Side mounting.  Expand the index 1 of the Mounting Data.  Set the “Mount Position” to “Right Side” and set the “Relative Mounting Offset” to <30.0, 50.0, 0.0>. This should translate to 30 minutes toward the front of the mount and 50 units to the right of the mount.

Notice the “Any Side” value for the options.  This is sort of an Omni mounting position, if there are no specific mounting points within a seat with one of the 6 relative directions than the system will attempt to retrieve an “Any” point as a last resort.  You can use the “any” point for quick debugging if you don’t care about the relative direction the player is at to move toward a seat.

7.2.2 Setup the Passenger Seat

Passenger Seat Setup
Fig 7.2.2.1 Passenger Seat Setup

The seat at index 1 should have the “Seat Id” of 1 automatically.  Set the “Seat Socket Name” to “s_PassangerSeat”.

Passenger Seat Mounting Data
Fig 7.2.2.2 Passenger Seat Mounting Data

Add two elements to the mounting data and expand them.  The first element will be the left side so set the “Mount Position” to “Left Side”.  Enter <-30, -50, 0> for the “Relative Mounting Offset.  This should translate to 30 units behind the mount origin, and 50 units to the left of the mount origin.

The Second element should be the right side so set the “Mount Position” to “Right Side”.  Enter <-30, 50, 0> which should translate to 30 units behind the mount origin and 50 units to the right of the mount origin.


8.0 Setup the Animation System

Return to Table of Contents

The final step we need is to setup our Animation System to support mounting our horse.  Since this tutorial is not using any Anim Montages for getting on or off we only need to worry about the actual mounted pose.  For a much more robust animation system where each mount has support for different mounting and dismounting animations for each seat as well as different mounted animations depending on the vehicle see the Final Project.

8.1 Event Graph

Animation Folders
Fig 8.1.1 Animation Folders

First thing I am going to do is duplicate the “ThirdPerson_AnimBP” and call it “ABP_MountingCharacter”. 

Animation BP Event Graph
Fig 8.1.2 Animation BP Event Graph

Now Open up the APB_MountingCharacter.  And double click on the EventGraph.

IsSeated Variable
Fig 8.1.3 IsSeated Variable

Create a new Bool variable and call it “IsSeated”.

TryGetPawnOwner
Fig 8.1.4 TryGetPawnOwner

For the most part we will simply be adding to the event animation graph.  From the “TryGetPawnOwner” Drag a line off of it.

Find IsSeated (Message) function
Fig 8.1.5 Find IsSeated (Message) function

Search for the IsSeatedOnMount(Message) function.

Is Seated On Mount
Fig 8.1.6 Is Seated On Mount

Connect the execution line from the last node of the event graph to the IsSeatedOnMount function.  Then Grab the IsSeated variable and set it to the value returned from the interface function.

That is all we have to do for the Event Graph

8.2 Anim Graph

Next we’ll setup the AnimGraph  while this tutorial does not leverage the AnimMontages I thought It would be nice to at least prepare our AnimBP for the use of them.

Anim Graph
Fig 8.2.1 Anim Graph

Next you will need to go to the AnimGraph.  I have renamed the State Machine to LocomotionStates.  I suggest you do the same as I reference it later on.

Select Cache Pose
Fig 8.2.2 Select Cache Pose

Drag a line from the outline of the figure and in the search box select “New Saved Cached Pose…” 

Renamed Cached Pose
Fig 8.2.3 Renamed Cached Pose

Name it “Locomotion”

Use Cached Pose
Fig 8.2.4 Use Cached Pose

Next right click and choose “Use cached pose ‘Locomotion’”

Search For Default Slot
Fig 8.2.5 Search For Default Slot

Now Drag the pose line out and search for the “Slot ‘DefaultSlot’” node. 

Default Slot
Fig 8.2.6 Default Slot

This is the node you will always select in a search regardless of the actual animation slot you are using.

Then Drag the Defaut slot pose line to the OutputPose node.

That is all for setting up the Anim Graph.

8.3 Locomotion States

Now we will setup the Animation States for our Mount.  I have a particular method I like to leverage but feel free to setup the Animation States however you see fit.

Moved Default Move States
Fig 8.3.1 Moved Default Move States

First thing to do is go into the Locomotion States State Machine graph.  And move the Four nodes already in there up, we will keep these for later.

New States
Fig 8.3.2 New States

From the “Entry” node draw out the execution line and create a new State called “OnGroundStates”  Then Create a second transition and State called “OnMountedStates”.  Finally create a transition from the “OnMountedStates” to the “OnGroundStates” states.

This should have the original 4 states and transitions disconnected from the entry.  You can leave them here for now or “Cut” or “Copy” them into your computer’s copy buffer.

On Ground States
Fig 8.3.3 On Ground States

Inside the OnGroundStates State right click and create a new State Machine and call it “GroundStates”. Connect the GroundStates pose pin to the Output Animation Pose node.

Ground States Graph
Fig 8.3.4 Ground States Graph

First go back to the top level of “LocomotionStates” and Cut the four disconnected states of “Idle/Run”, “JumpStart”, “JumpLoop”, and “JumpEnd”. 

Then Go back to “OnGroundStates” and into the “GroundStates” State Machine. 

Paste the Four copied States into this state machine.

Now our basic movement state machine should work perfectly fine while we are on the ground.

On Mounted States
Fig 8.3.5 On Mounted States

Now to back to the “LocomotionStates” and select the “OnMountedStates” State.  We will simply play the “A_Mounted” state while mounted.

Now our States are finished and we need to setup the transitions.

Ground to Seated Transition
Fig 8.3.6 Ground to Seated Transition

Double click on the Transition that is pointing from the “OnGroundStates” toward the “OnMountedSeats” States.  We want our animation system to transition to this state if we are seated on a mount.

Grab the IsSeated variable we created and connect it directly into the “Can Enter Transiton” node.

Seated to Ground Transition
Fig 8.3.7 Seated to Ground Transition

Now go back to the “LocomotionStates” and double click on the transition that is pointing from the “OnMountedSeats” toward the “OnGroundStates” states.  We want our animation system to transition back to the default ground movement when our character is no longer seated.

Grab the IsSeated variable we created and then drag it out.  Search for “NOT boolean” to get the “NOT” node.  Then drag that into the “Can Enter Transition” node.

Congratulations our Aniation System is setup and ready to go.

8.4 Assign the Animation Graph

Now we need to assign the animation graph.

Assign the Animation Blueprint
Fig 8.4.1 Assign the Animation Blueprint

Go to the BP_MountingCharacter blueprint and open it up.

Click on the "Mesh" Component.

In the "Animation Class" use the drop down and select "ABP_MountingCharacter".


9.0 Setup Completed

Return to Table of Contents

And that completes the basic setup for the seats and the entire mounting system.  At this point you are finished with the setup.  But running your game right now without an interaction system to start the mounting, dismounting, and seat changing procedures will not get you very far.  If you already have your own interaction system then you can simply hook up the mounting system into that and be sure to call the appropriate functions. 

The next steps will be setting up your interaction system.

If you already have an interaction system in place then you should simply need to know what functions you need to call to start the mounting process.

Interaction Systems

If you do not have an interaction system then you can follow the tutorial on how to setup a very basic interaction system

A Basic Interaction System