Mounting Plugin Guide 2.0

Hits: 245

Introduction

Welcome to the guided tutorial for the Pro Mounting System version 1.5 for Unreal Engine 4.23 and 4.24.  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.

Market Place: Pro Mounting System

Download Starting and Finished Projects

The mounting system was built using SOLID principles of programming with the primary mechanisms being Dependency Inversion and Dependency Injection.  This is what allows the Mounting system to be implemented across any game system without having to relying on any special Actors and Characters other than the base UE4 classes.

Table of Contents

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

1.0 Project Tour

2.0 Create the Basic Assets

3.0 Interface Component Setup

4.0 Interface Brief Overview

5.0 Player Controller

5.1 Implement the Player Controller

5.2 Controller Unified Interface

5.3 Rider Controller Interface

6.0 Player Character

6.1 Implement the Character

6.2 Character Unified Interface

6.3 MountRider Interface

7.0 Mount Setup

7.1 Mount Unified Interface

7.2 Mount Interface

8.0 Seat Setup

9.0 Animation Setup

10.0 SetupComplete

The Finished Project

I want to take a moment to talk about the finished project and some of the advanced techniques it demonstrates.  This tutorial is geared only towards a very basic setup to get you up and running, but things like Advanced animation techniques are not covered here.  However the downloadable Finished project demo demonstrates a fairly advanced animation system used to fetch animation data needed for a specific mounts dynamically and cleanly with no need to replicate montages or animation sequence assets.  This is an important technique to learn and know for UE4 in general as it allows you to scale up the mounting system beyond a single mount to an unlimited number of mounts and vehicles all capable of having their own unique ( mounting / dismounting / mounted ) animations and with little performance penalties, reduce animation blueprint complexity, and little to no network bandwidth for animations.

Another thing the Finished Project provides is a demonstration on how to handle blocking input to keep the player from rotating in their seat while mounted.

But most importantly the finished project offers several Blueprint Tutorials that guide you through what each completed system does including the animation system that has been added to it.

The Finished Project also includes other completed demonstrations:

  1. A fully functional 4 passenger Buggy.
  2. A 5 Passenger Buggy with added 5th seat Turret linked actor
  3. Demo on how to setup Player Mounting
  4. A two seat horse and player mount setup

While these do not have a BP Tutorial YET, a foundational knowledge of how the plugin works will get you far in figuring out these systems.

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.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

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:

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.2 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

Prepare to count yourself among the luckiest people in the world.  For the low low cost of this plugin you also receive 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.

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.1 Folder Structure

If it is not already created start by Creating the MountingContent folder.  Then create the Blueprints Folder, and the Maps Folder under it.

Save Map
Fig 2.1 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.2 Create New Character

Next go to “MountingContent/Blueprints” and create a new Blueprint Class from the ThirdPersonCharacter 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.3 Create Mount

Next Duplicate “PB_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.4 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.5 Create New Controller

Next Create a new Blueprint Class from the “PlayerController” base class and call it “BP_MountingPlayerController”.

Create new Game Mode
Fig 2.6 New Game Mode

Finally Create the GameMode we will be using for playing the game.  Call it “BP_MountingGameMode”.

Setup Game Mode
Fig 2.7 Setup Game Mode

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

World Settings
Fig 2.8 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.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”.  The propernames of these Interfaces are “IADMUnifiedControllerPawn” and “IMountRiderInterface” for those C++ devs.  We will go over what each of these interfaces do in the next section.

Add Rider Component
Fig 3.2 Add Rider Component

Next add the “MountRiderComponent to the component’s window of the BP_MountingCharacter class.  That is all we will do for now, the next sections will cover implementing the interfaces with the components.

Add Mount Interface
Fig 3.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”.  For you C++ programmers the proper names is “IMountablePawnInterface” and “IADMUnifiedControllerPawn”

Add Mount Component
Fig 3.4 Add Mountable Component

Next add the “MountablePawnComponent” to the component’s window of the BP_Horse.  Again this is all we will do for now as the next sections cover implementing these interfaces with the components.

Add Controller Interfaces
Fig 3.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.6 Add Controller Component

Next add the “RiderControllerComponent” to the component’s window of the BP_MountingPlayerController”.  The next sections will cover implementing the interfaces with these components.

4.0 Brief Interface Overview

Return to Table of Contents

This section will quickly go over the different interfaces and components and what they do.  For a more detailed explanation see the Documentation in the Documentation Link of the Plugin.

In general the three components of this system do not directly call each other, instead they call interface functions that then call other component functions.  This allows the entire mounting system to function without using any direct casts to specific objects other than the UE4 standard Actor, Pawn, and Object base classes.  With this flexibility it allows any Pawn to be a Rider or possessable mount and any Actor to be a non-possessable Mount.

IADMUnifiedControllerPawn

Put simply this interface unifies the Pawn and the Controller so that we can retrieve either one no matter which of these objects we get.  Naturally they follow the standard replication rules meaning that on multiplayer games only the Server will have all Controllers but client machines will be able to access their own controller and the pawns of other riders.  Basically follow standard UE4 client server rules when creating your gameplay logic and don’t assume pointers will point to things (check for null). 

This interface is most useful when dealing with unknown systems such as interaction systems.  You may have written your own interaction system or be using someone else's code to build your game.  Another example is leveraging UI where you want to get the Health of the Player instead of the Mount the player controller is controlling.  In the event that you are using some unknown code that needs to account for the mounting system you can use this interface to ensure you are playing with the Rider, the Controller, or the Mount regardless of which of these three objects is sent to that system as a parameter.

IRiderControllerInterface

This interface simply provides the basic function definitions needed for the Player Controller or even AIController to work properly.  

IMountRiderInterface

This interface provides the basic function definitions needed for the Player Character or an AI character to work properly with the mounting system.

IMountablePawnInterface

This interface provides the basic function definitions needed for a Mountable Pawn.

Depreciated Functions

Depreciated Functions
Fig 4.1 Depreciated Functions

You may notice that within the interface side panel a special category called “Depreciated”.   These are older functions that where implemented on a previous version of the Unreal Engine.  Rather than removing these functions from the interfaces I have opted to do a stepped depreciation.  Usually these will be followed by a number indicating the version of UE4 that the functions will stop being called from the internal system.

The First Step is a Soft Depreciation, these functions are simply placed within a depreciated category but all logic that calls them from within the components is not changed.  They will still be called by the components but their return values will be checked for invalid values and the replacement function will then be called instead.

The Second Step is hard depreciation. All logic that originally called that function is removed and if there are newer functions they will completely take over.

The third step is removal of the function from the interface.

Each step represents an entire engine version.  So if a function is depreciated in UE 4.24 it is put into the deprecated category immediately.  In Version UE 4.25 any logic within the components that once called that function is then removed.  In UE 4.26 that function is then removed from the interface completely.

This is designed to allow developers time to properly upgrade from one version of the engine to another without completely losing functionality and having to reimplement logic.

5.0 Implement the BP_MountingPlayerController

Return to Table of Contents

This section we will go over the easiest system to implement, the controller.  In a later section or 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.

5.1 General Setup

Setup the Owned Pawn

Override On Possess
5.1.1 Override On Possess

One of the first things we need to do is tell the RiderControllerComponent what the main pawn it controls should be.  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 a pawn. 

On Possess
Fig 5.1.2 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.  There are Three properties to be aware of; the OwnedPawn, the MountPawn, and the ControlledPawn.  The owned pawn is the original character that the component always keeps a reference to. The mount pawn is of course the mount the owned pawn is currently sitting on. The controlled pawn is the pawn that the controller is currently controlling. 

The special feature of the “SetControlledPawn” function is that if the component does not currently have a reference to the owned pawn, than the first pawn passed into it will be set as the owned pawn and all subsequent pawns passed into it will be treated as mount pawns.

You can override this by calling “SetOwnedPawn” or “SetMountPawn” but generally you do not need to do this.

Setup the RpcGraph

Setup RPC Graph
Fig 5.1.3 Setup RPC Graph

For online games we need to prepare for input and RPC calls to the server.  I personally create separate event graphs for this work to keep my code organized.  Create an InputGraph and an RpcGraph.  We will not go over input just yet but will setup the RpcGraph.  Again later I will show you how to build a rudimentary interaction system where we set this up.

Server Possess Pawn
Fig 5.1.4 Server Possess Pawn

Create a new “CustomEvent” called “SERVER_PossessPawn”.  Drag out the PossessCharacter Interface function and then drag the CharacterToPosses line from the “PossessCharacter” function to the “SERVER_PossessPawn” function creating an input variable.

Details of Server Possess Pawn
Fig 5.1.5 Details of Server Possess Pawn

Make sure the Replicates property is set to “Run on Server” and the Reliable flag is checked.

5.2 IADMUnifiedControlerPawn for the PlayerController

Return to Table of Contents

Prepare to Mount

Prepare To Mount
Fig 5.2.1 Prepare To Mount

Implement prepare to mount by getting the RiderControllerComponent and calling “PerformMountPawn”, passing the “MountOrRider” and “LinkedActor” parameter through to it.   Then connect the output as shown in the image.

You don’t actually have to implement this function this way.  You can simply return true.  However To start the mounting process you need some object to call PerformMountPawn from the RiderControllerComponent.  That function is the function that starts the mounting process and you must provide it the Mount you want to start mounting onto.   I simply use this function as an easy method to trigger the system.

The second Parameter “LinkedActor” is optional and is not required for the linked actor mounting to work.  Say you have a mount with several seats and one is a turret, you can setup your turret to be interactable and supply itself as the Linked Actor Parameter to this function allowing you to directly mount the turret seat.

The PreformMountPawn function calls PrepareToDismount for the Pawn and the Mount as well, if any of those two return a false for those functions then the entire mounting procedure is canceled.  These prepare functions are specifically designated to allow you to configure any custom properties you want to set up and/or stop the mounting process early.

Prepare to Dismount

Prepare To Dismount
Fig 5.2.2 Prepare To Dismount

Implement by calling “PerformDismountPawn” function of the RiderControllerComponent.  Connect the dots as shown in the image.  Just like “PrepareToMount” you do not need to use this function to start the dismounting process, simply return true.  But like PrepareToMount you need a way for your system to call “PerformDismountPawn” from the RiderControllerComponent and supply it the old mount.

Is Mounted

Is Mounted
Fig 5.2.3 Is Mounted

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

Get Character Pawn

Get Character Pawn
Fig 5.2.4 Get Character Pawn

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

Get Character Mount

Get Mount
Fig 5.2.5 Get Mount

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

Get Character Controller

Get Controller
Fig 5.2.6 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.  

5.3 Implement IRiderControllerInterface

Return to Table of Contents

PossessCharacter

Possess Character
Fig 5.3.1 Possess Character

Begin with the “SwitchHasAuthority” Macro which determines if we are the authority (on the server) or if we are the remote (on the client). 

From the “Authority” Arrow call “Possess” and supply the “CharacterToPosses” parameter to the “InPawn”.  Connect the line from the “Possess” function to the return node and return true.

From the remote line of “SwitchHasAuthority” call “SERVER_PossessPawn” and supply the “CharacterToPossess” parameter.

Now the Mounting Process calls this function to take possession of a given character or mount depending on what context this call is being fired.

OnRiderAdded

On Rider Added
Fig 5.3.2 On Rider Added

The Implementation of this function is completely optional and is used by the Mounted Actor to notify other riders that a new rider has been added effectively taking up a seat on the mount.

There are two methods to implementing this function and provide two levels of dealing with this notification.  The first is to directly within the interface function itself.

Component Delegates
Fig 5.3.3 Component Delegates

If you decide to implement this with the RiderControllerComponent and call RiderAdded function, passing the properties in, you can then also implement the delegate function of the RiderControllerComponent OnRiderAdded

OnRiderRemoved

On Rider Removed
Fig 5.3.4 On Rider Removed

The implementation of this function is completely optional and is used by the Mounted Pawn to notify other riders that a rider has left the mount or vehicle.  Effectively indicating that another seat is available and can be moved to.

There are two methods to implementing this function and provide two levels of dealing with this notification.  The first is directly on this interface function itself. 

If you decide to implement this with RiderControllerComponent and call RiderRemoved, passing the properties in, you can then also implement a delegate function of the RiderControllerComponent OnRiderRemoved.

OnOtherRiderChangedSeat

On Other Rider Changed Seats
Fig 5.3.5 On Other Rider Changed Seats

 

The implementation of this function is completely optional and is used by the Mounted Pawn to notify other riders that a rider has changed from one seat to another within the mount or vehicle.  Effectively indicating that another seat is available and can be moved to.

There are two methods to implementing this function and provide two levels of dealing with this notification.  The first is directly on this interface function itself.  

OnMountActionFailed

On Mount Action Failed
Fig 5.3.6 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.

OnDismountActionFailed

On Dismount Action Failed
Fig 5.3.7 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.

OnChangeSeatActionFailed

On Changed Seat Action Failed
Fig 5.3.8 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.

GetRiderControllerComponent

Get Controller Component
Fig 5.3.5 Get Controller Component

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

6.0 Implement the MountingCharacter

Return to Table of Contents

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

6.1 General Setup

Relative Location and Rotation
Fig 6.1.1 Relative Location and Rotation

One of the major things you need to do is set the “RelativeMeshLocation” and “RelativeMeshRotation” properties for the component.  These properties are used to reset the client side mesh component that gets offset from the capsule due to attachment and detachment replication.  For the Standard mannequin this is simply setting the Z values of both Location and Rotation to -90 (maybe give or take a few points if you are a perfectionist).  \

Mesh Details
Fig 6.1.2 Mesh Details

These are the exact same values found in the Mesh Component’s transform properties of any ACharacter.  Simply copy and paste.

Optional Constructor Setup
Fig 6.1.3 Optional Constructor Setup

You can Automate these by having them automatically updated in the Pawn’s ConstructorScript function

Behavior Settings
Fig 6.1.4 Behavior Settings

The other thing to be aware of are the two properties “PossessMountAfterAnimation” and “PossessCharacterAfterAnimation” these properties tell the mounting system when to take possession of the mount or the player during the mounting and dismounting processes. 

PossessMountAfterAnimation is used for mounting.  It means that the character will take control of the mount once the mounting animation finishes and the character is firmly on the seat, if this is false than they will take possession of the mount immediately after moving into position to start mounting. 

PossessCharacterAfterAnimation is used for dismounting.  It means that the system will retake possession of the character once the dismounting animation has completed.  If this is false then repossession occurs immediately after starting dismounting.

Move to Location

I am going to preface this with; this by no means is the best way to move your character into place for mounting and there are way way way better means to do this.  But for demonstration purposes I am simply interested with ensuring the logic works.

Perform Move to Location
Fig 6.1.5 Perform Move To Location

Start with creating a custom Event and calling it “PerformMoveToLocation”  Then right click and search for a function called “MoveComponentTo”.  Grab the Capsule Component and drag it into the “component” parameter. 

Then take the “TargetRelativeLocation” and “TargetRelativeRotation” and drag a line from the “MoveComponentTo” function to the space just below the execution Line of your new “PerformMoveToLocation” function to create two new inputs for it.  Now set the “OverTime” parameter to 2 seconds.

Drag the completed line out and call “OnMoveToMountingLocationComplete”

I’m going to say this again, this is a terrible way to do this but getting into Cinematics or AI is not part of this tutorial.  While I may find time one day to implement a more sophisticated method of doing this, for now it gets the job done.

6.2 Implement ADMUnifiedControllerPawn for Character

Return to Table of Contents

Prepare to Mount

Prepare To Mount
Fig 6.2.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.

Prepare to Dismount

Prepare To Dismount
Fig 6.2.2 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.

Is Mounted

Is Mounted
Fig 6.2.3 Is Mounted

Implement the characters “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.

Get Character Pawn

Get Character Pawn
Fig 6.2.4 Get Character Pawn

For GetCharacterPawn simply return self.

Get Character Mount

Get Mount
6.2.5 Get Mount Pawn

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.

Get Character Controller

Get Controller
Fig 6.2.6 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.

6.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.

StartPawnMounting

Start Pawn Mounting
Fig 6.3.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.

StartPawnDismounting

Start Pawn Dismounting
Fig 6.3.2 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.

SetRiderCollisionEnabled

Set Rider Collision Enabled
Fig 6.3.3 Set Rider Collision Enabled

This function allows you to control how collision is disabled and enabled on the player while mounted.  The primary requirement for ACharacter objects is that the Capsule Component collision be disabled to prevent the Character logic 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.

OnMountingPawnFinished

On Mounting Pawn Finished
Fig 6.3.4 On Mounting Pawn Finished

This is the final step to mounting that needs to be called in order to finish the mounting process.  Several properties are finalized when this function is called, among them the flag indicating your character is officially “seated” on the mount.

If you have no animations to play for mounting than this function is called automatically.  However if “PlayMountingAnimation” function implements an animation to play then that animation needs to use an AnimNotify to call this interface function. 

Mounting Finished Anim Notify
Fig 6.3.5 Mounting Finished Anim Notify

You can do this manually or use the “MountFinished” AnimNotify that this plugin comes with.

OnDismountPawnFinished

On Dismount Pawn Finished
Fig 6.3.6 On Dismount Pawn Finished

This is the final step to dismounting that needs to be called in order to finalize the dismounting process.  Like mounting, several properties are cleared with this function and detaches from the mount.

If you have no animations to play for mounting than this function is called automatically.  However if “PlayDismountingAnimation” implements an animation and returns true instead of false then the playing animation needs to use an AnimNotify to call this interface function.

Dismount Finished Anim Notify
Fig 6.3.7 Dismount Finished Anim Notify

You can manually implement your own anim notify or you can use the “DismountFnished” anim Notify that comes with the plugin.

There are also a few considerations to take into account with dismounting.  Many of them the Mounting System handles itself such as mesh offset caused by dismounting for characters.  Other issues such as stopping the play of AnimMontages or having an AI controller repossess the mount if you are the driver are not covered.  Dismounting a mount you are currently driving while moving will preserve its current movement vector on the client without having an AI controller retake control.  These are all quarks of UE4 itself.

OnChangeToNewSeatCompleted

Change to New Seat Completed
Fig 6.3.8 Change to New Seat Completed

This is the final step of the changing seats procedure and needs to be called in order to finalize the change seats process.  Several properties are cleared with this function and finishes attaching the pawn to the proper new seat location.

If you have no animation that plays for seat changing this function is called automatically.  However if “PlayMoveToSeatAnimation” plays an animation and returns true instead of false then the Playing Animation needs to use an AnimNotify to call this interface function

Change to New Seat Anim Notify
Fig 6.3.9 Change to New Seat Anim Notify

You can manually implement your own AnimNotify or you can use the “ChangeSeatsFinished” Notify that comes with this plugin.

MoveToMountingLocation

Move to Mounting Location
Fig 6.3.10 Move to Mounting Location

This function is called to start your pawn toward moving to its desired location before mounting.  There are many many ways to implement this and I am currently using the most wonkiest one of them all. 

Call the function we set up earlier [Anchor]PerformMOveToLocation[Anchor].  Passing in the Location and Orientation.  Then return true. 

You can also simply leave this function as it is with it simply returning false.  The mounting system will pick this up, jump immediately to the character in the desired location and start the mounting animation (if you have any).

OnMoveToMountingLocationCompleted

Move to Mounting Location Complete
Fig 6.3.11 Move to Mounting Location Complete

This is one of those functions that can be called from many different sources and depends on if you have logic for moving the character into a specific location.  To implement it you simply get the “MountRiderComponent” and call “MoveToMountingLocationComplete”.

Here you can also do some additional checks, maybe the mount has moved away from you and is now too far than the original mounting location.  Of course there are methods to this but when another player is controller your mount or you are not updating the mounting location dynamically through AI or other means it could happen. 

In the event you need to “bail out” of a mount due to the above cases you’ll need to add some Bail out logic to clear the seat on the mount and call the Reset function on the Controller and Character.

If the [anchor]“MoveToMountingLocation”[anchor] function simply returns false than this function is automatically called by the mounting system and assumes you have no logic in place to move the player to the desired location.   

IsSeatedOnMount

Is Seated On Mount
Fig 6.3.12 Is Seated On Mount

To implement this function we will simply grab the MountRiderComponent as a Get, then convert it to a Validated Get.  From “MountRiderComponent” call the function “IsSeated” and return it in the IsValid state.  For the IsNotValided execution line simply return 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.

IsDriver

Is Driver
Fig 6.3.13 Is Driver

Get the MountRiderComponent and convert it to a Validated Get.  From the IsValid Execution line call MountRiderComponent’s “IsDriver” function and return it.  From the IsNotValid execution line simply return false.

This function uses the Validated Get because it may be used for Animation Graphs which continue to update animation during shutdown and after components have been destroyed and garbage collected.

GetRiderMesh

Get Rider Mesh
Fig 6.3.14 Get Rider Mesh

This function simply returns the master mesh component of the player.

GetMountRiderComponent

Get Rider Component
Fig 6.3.15 Get Rider Component

This function simply returns the MountRiderComponent itself.

GetAllRiderSkeletalMeshes

Get all Rider Skeletal Meshes
Fig 6.3.16 Get all Rider Skeletal Meshes

This function takes some special mentions, you may ask why is this here.  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.

PlayMountingAnimation

Play Mounting Animation
Fig 6.3.17 Play Mounting Animation

I will not be explaining the intricacies of a fully dynamic animation system in this tutorial.  In the final project I have a fully working demonstration of how you can supply animations per mount for your character that you are free to steal and use for your own games.  For this tutorial however simply return false. This will cause the mounting system to automatically proceed with the mounting system.

PlayDismountingAnimation

Play Dismount Animation
Fig 6.3.18 Play Dismount Animation

I will not be explaining the intricacies of a fully dynamic animation system in this tutorial.  In the final project I have a fully working demonstration of how you can supply animations per mount for your character that you are free to steal and use for your own games.  For this tutorial however simply return false. This will cause the mounting system to automatically proceed with the mounting system.

PlayMoveToSeatAnimation

Play Move To Seat Animation
Fig 6.3.19 Play Move To Seat Animation

I will not be explaining the intricacies of a fully dynamic animation system in this tutorial.  In the final project I have a fully working demonstration of how you can supply animations per mount for your character that you are free to steal and use for your own games.  For this tutorial however simply return false. This will cause the mounting system to automatically proceed with the mounting system.

7.0 Implement the Mount Character

Return to Table of Contents

This section we will get to the important details of implementing the Mount Character or Vehicle so it can perform the Mounting.

General Setup

Because we are dealing with a character type for this horse 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 clients even though they are staying still on the server.  This appears to be only an issue with the UCharcterMovementComponent found on ACharacter base classes.  APawns with no movement component or AVehicle based classes do not appear to have the issue.

Set AIController Reference
Fig 7.0.1 Set AIController Reference

First thing we will do is create a custom variable to hold our AI Controller.  Any AIController will work including the default one which does nothing.  We'll call it "AIControllerRef" and it will be of the "Controller" type.  This will not be a replicated value as all controllers only exist on the servers.

Search for Possessed
Fig 7.0.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 that and type "Possess" to find the Possessed Event function and click on it.

Override Possessed
Fig 7.0.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 and that will be the first controller that we set to our parameter.  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.  We first test if our AIControllerRef variable is valid, if it is we leave it alone, if it is not than we set the controller to it.

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

7.1 Implement ADMUnifiedControllerPawn for Mount

Return to Table of Contents

This section covers implementing the ADMUnifiedControllerPawn interface for the mount

Prepare to Mount

Prepare To Mount
Fig 7.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 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 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.

Prepare to Dismount

Prepare to Dismount
Fig 7.1.2 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.

Is Mounted

Is Mounted
Fig 7.1.3 Is Mounted

Grab the MountablePawnComponent and return the value of “IsMounted”.

Get Character Pawn

Get Character Pawn
Fig 7.1.4 Get Character Pawn

For Mounts we return their driver for this function.  Get the MountablePawnComponent and return the value of its “GetDriver” function.

Get Character Mount

Get Character Mount
Fig 7.1.5 Get Character Mount

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

Get Character Controller

Get Character Controller
Fig 7.1.6 Get Character Controller

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

7.2 Implement MountablePawnInterface

Return to Table of Contents

This section covers the implementation of the IMountablePawn Interface.

MustHaveDriver

Must Have Driver
Fig 7.2.1 Must Have Driver

Get the MountablePawnComponent and use it to call “MustHaveDriver” and return its value.

IsMountableActor

Is Mountable Pawn
Fig 7.2.2 Is MountabountablePawnComponent le Pawn

Get the MountablePawnComponent and call “CanMount” and return it’s value.

IsMountableByPawn

Is Mountable By Pawn
Fig 7.2.3 Is Mountable By Pawn

For demonstration purposes this function will simply return true.  This is a special function to test if the specified pawn is capable of mounting the vehicle.  Often used in conjunction with “PrepareToMount” you can setup specific logic to determine if the pawn can or cannot mount due to some conditions that need to be meet.  

IsDriverSeat

Is Driver Seat
Fig 7.2.4 Is Driver Seat

Get the MountablePawnComponent and call “IsDriverSeat”.  Pass in the “Seat Data” parameter and return the function’s value.

IsDriverReady

Is Driver Ready
Fig 7.2.5 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.

HasPassangers

Has Passengers
Fig 7.2.6 Has Passengers

Get the MountablePawnComponent and then call “GetNumRiders”.  If the value is greater than zero than the mount has passengers.  This includes the driver.

HasDriver

Has Driver Seat
Fig 7.2.7 Has Driver Seat

Get the MountablePawnComponent and call its “HasDriver” function, returning the bool value.

GetRelativeMountDirection

Get Relative Position To Mount
Fig 7.2.8 Get Relative Mount Direction

For this demonstration we will be assuming that our horse mount can only be mounted from the left or right side.  This function allows each individual mount to specify the different possible directions it could be mounted from. 

We will use special Mounting Library function “GetAngleFromRightBetweenActors”.  Pass a reference of “self” as the “Main Actor” parameter and the “Rider” as the “TargetActor” parameter.  If the Value returned is greater than or equal to zero we will return that we want mounting to occur on the right side of the mount, if it is false than we want mounting to occur on the left side of the mount.

The available options include, Front, Back, Left, Right, Top, Bottom, Any. When the system searches for seats it will prioritize the 6 directional options first, then if none of those options are found it will attempt to find an Any option if one exists.

There are three general functions you can call to determine the rider’s general location relative to the mount's current forward direction.

GetAngleFromRightBetweenActors will tell you if the potential rider is currently relatively on the right side of the mount if it returns a value between 0 and 1 and left side of the mount if it’s value is between -1 and 0.  If the value is equal to 0 then it is directly in front or directly behind the mount.  In this demonstration we do not care about front and back and assume 0 to be right side mounting.

GetAngleFromFrontBetweenActors will tell you if the potential rider is currently relatively at the front side of the mount if it returns a value between 0 and 1; and on the back side if the value is between -1 and 0;  If the value is equal to 0 then it is directly on the right or left side of the mount.

GetAngleFromUpBetweenActors will tell you if the potential rider is currently relatively above the mount if its value is between 0 and 1; and below it if it’s value is between -1 and 0.  If it’s value returns 0 than it could be anywhere along the horizon of the mount (Front, Back, Left, or Right).

GetRelativeDismountDirection

Get Relative Dismount Direction
Fig 7.2.9 Get Relative Dismount Direction

For Demonstration purposes we will be using a new function of the 2.0 version of the plugin that will get the default position for a specified seat.  This simply returns the first entry in the seat’s “MountingData” array, which for most vehicles will be the only entry. Our horse however has each seat mountable on the left and the right side so depending on which side is first that side will be the one chosen.

First we get the current Seat ID of the rider that is dismounting.  Then get the MountablePawnComponent and call it’s “GetDefaultPositionForSeatById” function and pass in the seat id.  Finally feed that result 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.

GetMountBody

Get Mount Body
Fig 7.2.10 Get Mount Body

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.  

GetMountablePawnComponent

Get Mountable Pawn Component
Fig 7.2.11 Get Mountable Pawn Component

This simply returns the MountablePawnComponent

GetMaxRiders

Get Max Riders
Fig 7.2.12 Get Max Riders

Get the MountablePawnComponent and call “GetNumSeats” and return the value.

GetDriver

Get Driver
Fig 7.2.13 Get Driver

Get the MountablePawnComponent and call “GetDriver” and return the value.

GetCurrentRiderCount

Get Current Rider Count
Fig 7.2.14 Get Current Rider Count

Get the MountablePawnComponent and call “GetNumRiders” and return the value

FindAvailableMountingPosition

Find Available Mounting Position
Fig 7.2.15 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.

IsSeatOccupiedById

Is Seat Occupied By Id
Fig 7.2.16 Is Seat Occupied By Id

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

IsSeatOccupiedAtIndex

Is Seat Occupied By Index
Fig 7.2.17 Is Seat Occupied By Index

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

SetSeatOccupiedById

Set Seat Occupied By Id
Fig 7.2.18 Set Seat Occupied By Id

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

SetSeatOccupiedAtIndex

Set Seat Occupied At Index
Fig 7.2.19 Set Seat Occupied At Index

Get the MountablePawnComponent and call its SetSeatOccupiedAtIndex. Pass “Seat Index” and “Rider” parameters into the function and return the output

ClearSeatById

 Clear Seat By Id
Fig 7.2.20 Clear Seat By Id

Get the MountablePawnComponent and call its “ClearSeatById” function.  Pass in the “Seat Id” parameter and return the functions value.

ClearSeatByIndex

Clear Seat At Index
Fig 7.2.21 Clear Seat At Index

Get the MountablePawnComponent and call its “ClearSeatByIndex” function.  Pass in the “Seat Index” parameter and return the functions value. (Unfortunately this function does not follow the normal naming convention of GetById and GetAtIndex).

GetSeatDataById

Get Seat Data By Id
Fig 7.2.22 Get Seat Data By Id

Get the MountablePawnComponent and call is “GetSeatDataById”. Pass in the “Seat Id” parameter and return the output.

GetSeatDataAtIndex

Get Seat Data At Index
Fig 7.2.23 Get Seat Data At Index

Get the MountablePawnComponent and call is “GetSeatDataAtIndex”. Pass in the “Seat Index” parameter and return the output.

CanMountActor

Can Mount Pawn
Fig 7.2.24 Can Mount Pawn

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.

CanMountAtPosition

Can Mount At Position
Fig 7.2.25 Can Mount At Position

Though this function is never used by the internal system itself you could use it for validate seating operations.  To implement this I simply grab the “Find Available Mounting Position” function we implemented earlier and pass in the “Rider Location” and “Desired Mounting Position” parameters to it.  Then simply return the return value.

OnRiderFinishedMounting

On Rider Finished Mounting
Fig 7.2.26 On Rider Finished Mounting

This function is mainly used when you want to provide signaling to other riders or players that someone has gotten onto the mount.

Get the MountablePawnComponent and call “RiderFinishedMounting”.  Pass the “Mounted Actor” and “Seat Id” into the function and return true.  The return value holds no significance in this function, only to ensure that it is implemented as a function and not an event.

The RiderFinishedMounting function will loop through all the current riders and send them an update indicating that a rider has been added.  How this signal is handled is dependent on how you implemented the IMountRider Interface function “OnMountingPawnFinished”.

OnRiderFinishedDismounting

On Rider Finished Dismounting
Fig 7.2.27 On Rider Finished Dismounting

This function is mainly used when you want to provide signaling to other riders or players that someone has gotten off the mount.  But we will also use it to signal to the mount’s AI Controller that it needs to retake possession of mount.

We will start with getting the MountablePawnComponent and call “RiderFinishedDismounting”.  Pass the “Dismounted Actor” and “Seat Id” parameters into the function.  The return value of this function is to simply ensure it is implemented as a function in blueprints and not as an event.

The RiderFinishedDismounting function will loop through all the current riders and send them an update that one of the passengers has been removed.  How this signal is handled is dependent on how you implemented the IMountRider Interface function “OnDismountingPawnFinished”.

AI Repossession
Fig 7.2.28 AI Repossession

The second half of this function we will return 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”

First we check if the sent in set ID is 0 (our driver seat).  If it is than we check if the AI Controller is valid.  If it is Than we possess the mount.  Because the AIControllerRef should not have any value on the client side we should not need to put a HasAuthority here, but I would still suggest doing so.

OnRiderFinishedChangingSeats

[Image of OnRiderFinishedChangingSeats]

On Rider Finished Changing Seats
Fig 7.2.29 On Rider Finished Changing Seats

This function is mainly used when you want to provide signaling to other riders or players that a fellow passenger has taken a different seat.  We will also leverage it to have the AI Controller retake possession of the just like we did in OnRiderFinishedDismounting.

Get the MountablePawnComponent and call “RiderFinishedChangingSeats”.  Pass the “Rider”, “NewSeatId”, and “OldSeatId” into the function.

The “RiderFinishedChangingSeats” function will loop through all the current riders and send them an update that the specified rider has changed positions.  How this signal is handled depends on how you implemented the IMountRider Interface function “OnChangedToNewSeatCompleted” function.

[Image of AI Repossession ]

AI Repossession
Fig 7.2.30 AI Repossession

The second half of this function we will return to the AIController we setup earlier.  If the seat we just moved 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”

First we check if the “Old Seat Id” sent is is 0 (our driver seat).  If it is than we check if the AI Controller is valid.  If it is Than we possess the mount.  Because the AIControllerRef should not have any value on the client side we should not need to put a HasAuthority here, but I would still suggest doing so.

8.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.

8.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 8.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 <0.0, -11.0, -20>  and a relative rotation of <0.0, -34.0, -90>.

The “s_PassangerSeat” is attached to the “b_spine_02” bone.  It has a relative location of <0.0, 2.0, 18.0> and a relative rotation of <0.0, 0.0, -90.0>.

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).

8.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 8.2.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 8.2.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.

Setup Driver Seat

Driver Seat Setup
Fig 8.2.3 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 8.2.4 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.

Setup the Passenger Seat

Passenger Seat Setup
Fig 8.2.5 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 8.2.6 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.

9.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.

9.1 Event Graph

Animation Folders
Fig 9.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 9.1.2 Animation BP Event Graph

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

IsSeated Variable
Fig 9.1.3 IsSeated Variable

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

TryGetPawnOwner
Fig 9.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 9.1.5 Find IsSeated (Message) function

Search for the IsSeatedOnMount(Message) function.

Is Seated On Mount
Fig 9.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

9.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 9.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 9.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 9.2.3 Renamed Cached Pose

Name it “Locomotion”

Use Cached Pose
Fig 9.2.4 Use Cached Pose

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

Search For Default Slot
Fig 9.2.5 Search For Default Slot

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

Default Slot
Fig 9.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.

9.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 9.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 9.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.

[Image of OnGroundStates]

On Ground States
Fig 9.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 9.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 9.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.

[Image of GroundToSeatedTransition]

Ground to Seated Transition
Fig 9.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.

[Image of SeatedToGroundTransition]

Seated to Ground Transition
Fig 9.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.

10.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. 

If you followed this tutorial to the letter then that means your interaction system will need to call the Controller’s IADMUnifiedPawnController Interface function PrepareToMount passing the desired mount into it as a parameter.  To Dismount you’ll need to call the IADMUnifiedPawnController interface function PrepareToDismount and pass the current mount to it as a parameter.

If you didn’t follow the tutorial exactly than do not worry, the real magic of the system actually starts with the Controller’s RiderControllerComponent’s function “PerformMountPawn” for starting the mounting procedure, you just need to supply the mount you want to mount to it as a parameter.  For dismounting the real magic lies in the Controller’s RiderControllerComponent’s function “PerformDismountPawn”, again passing the current mount into it for dismounting.

You can continue to set up a basic interaction system by following the next link below.

10.1 Online Documentation

I would like to thank you for purchasing and using this product that I have spent an extraordinary amount of time building, perfecting, and enhancing over the last year.  If you have any questions feel free to use my contact page to direct questions to me.

How to Find Documentation Link
Fig 10.1.1 How to Find Documentation Link

For those who have purchased the server you can access additional documentation from the “Documentation” link found in the Plugin Description.  There you will also gain access to a link to my Discord Server where you can directly message me and talk to others who are using the Mounting System.

Print