Combat System Tutorial: Intro

Introduction

Welcome to Part 1 of the guided tutorial series for the Pro Networked Combat System (PNCS) for Unreal Engine 4.25. The PNCS is not so much a combat system as it is a Combat Framework.  It is designed in such a way that it should be possible to implement any combat system you desire.  For this reason the totality of the tutorials on how to use the PNCS will be broken up into several smaller tutorials.  This tutorial will be the first and it’s primary goal is to setup the project as a starting point for the other tutorials. To follow along you will need to have purchased the plugin from the Unreal Marketplace.  You can create a new project and follow along from scratch but I suggest downloading the example starting project to follow along as it contains animations required that are already setup and ready to go.

Get the plugin at: UE4 Marketplace

Starting Project Download

Finished Project Download

The PNCS system was built using S.O.L.I.D. principles with the primary mechanism being Dependency Inversion and Dependency Injection.  This is what allows the PNCS system to be implemented across any game with no reliance on pre-built Characters and Actors or the need for a long and confusing chain of inherited blueprints or CPP classes.

The Finished Project

In time the finished project will become more and more robust allowing you to preview various methods of implementing the combat system and supporting systems along with it such as some advanced animation techniques or different types of games.  Because this is the initial launch of the combat system it will only contain the finished tutorials, but over time you will be able to see more complicated systems and will be free to leverage those implementations however you desire.  In such examples I always provided a built in Blueprint Tutorial that accompanies each additional example.

Overview

Through out this tutorial series we will be developing a total of 4 demos to get you up and running with the Combat system and hopefully in a way you come to understand all the various parts of the combat system.  This initial tutorial is geared towards getting the project setup and preparing it for the other example demo systems we will be working through.  Through this tutorial series we will develop a basic combat system that allows you to equip weapons, attack an opponent, defend from an incoming attack, and deflect blocked attacks that stun the attacker.  In each of the four demos we will be building on this combat system. 

As noted the first tutorial is an intro and will setup our work space to develop the other four by establishing some common code each will leverage. 

The Second tutorial will focus completely on using the Weapon Manager and the Weapon Actors without leveraging the Action Manager.  We will get a taste of what is needed to build a combat system without utilizing the Action Manager and how we can implement the features of Attack, Guard, and Stun.  Some games may not need the sophistication of the Action Manager which is why it is an optional but powerful component of the combat system.  However, because the action manager is a powerful tool this is the only tutorial that will not leverage it.  This will be a Melee weapon only tutorial as well and will introduce the Sword Pickup object.

The Third tutorial focuses on the Action Manager and how to implement the various actions such as Attacking, Guarding, and the Stunned State which is an action in of itself.  This will also be a Melee only tutorial and utilize the sword pickup object.

The Fourth tutorial will implement ranged attacks using the Action Manager.  We'll add a Bow and arrow pickup, implement ammo loading and display, as well as ammo management.  These will be simplified examples but you or your developer should be able to extrapolate how to perform more advanced operations such as querying specific ammo in your inventory rather than a generic catch all ammo that we will be utilizing.

The fifth and final tutorial will swap out both our unarmed and sword weapons for precision weapons.  Weapons that perform tracing along with the animation to give as realistic a hit result as possible.

Table of Contents

 

1.0 Project Tour

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

[IMAGE: 1.0_TUTORIALS]

For the starting project itself, it is much more stripped down and bare bones. But I will go over some of the key things you need to know about.

1.1 Templates and Content

[IMAGE: 1.1.1_ThirdPersonBPFolder]

You'll notice the project includes the Unreal Engine Third Person Blueprint Template.  Most of this tutorial will be leveraging the Third Person Template and because we will in some instances be editing the input it is easier to use the Blueprint version of that template over the C++ version. We will also be leveraging the Third Person Map, but this is less important than the ThirdPersonBP itself.  You can use any map you want.

[IMAGE: 1.1.2_OtherContent]

I always leverage the ExampleContent and the "StarterContent" because it is useful for prototyping.  The Mannequin folder is required as we will be working with the UE4 Mannequin and it's animations.

1.2 The Common Folder

[IMAGE: 1.2.1_COMMON_FOLDER]

In the starting project there is a folder under "ExampleContent" called "Common"  Here you will find some of the globally useful things we will need for all projects.  Two important folders are found here. The "Animation" folder and the "Props" folder. 

[IMAGE: 1.2.2_PROPS_FOLDER]

The "Props" folder holds all the visual assets for the various weapons the combat system comes with for testing.  This includes a Sword, Shield, Knife, Great Sword, Bow, and Arrow meshes and materials.

[IMAGE: 1.2.3_ANIMATION_FOLDER]

The "Animations" Folder holds all the custom build animations I have provided with the combat system.  They are not the best as I am not a professional animator nor did I bother to use motion capture.  I simply built assets using blender that gave an approximation of what I would need.  The Animations folder breaks down into "Bow", "H2H', and "Melee" sub folders.  Bow holds all the animations relevant to using the bow weapon, "H2H" is the animations for unarmed combat, and "Melee" holds all animations for the sword weapon and is used for all other melee based weapon assets such as the dagger and great sword.  One day I may develop animations for these for demonstration but right now it gets the job done.

2.0 Basic Setup

In this section we will be setting up our project for development by creating the folders for our project.  Each of our four demos we develop will have their own folder and be for the most part self contained.  As a note this is how I setup all my projects and it does wonders keeping things organized.

[IMAGE: 2.0_DemoContentFolder]

Start by creating the root folder for all the tutorials we will be leveraging.  We'll call it "DemoContent". 

[IMAGE: 2.0_CoreFolder]

Next create a "Core" folder under the "DemoContent" folder.  This folder is where we will put most of the shared data that will be leveraged by all of the demos.

[IMAGE: 2.0_BlueprintsFolder]

Next create a "Blueprints" folder under the "Core" folder.  This folder is where we will put all Blueprints we will use to build out the global logic for the demo.  This will also be the main folder we use for this demo.

[IMAGE: 2.0_Data]

Next create the "Data" folder under the "Core" folder.  This folder is where we will be holding any Data related assets for our demos.  This includes Data Assets, Data Tables, and String Tables (if you are using them).

[IMAGE: 2.0_CharacterFolder]

Next create a "Character" Folder under the "Blueprints" folder.  This is where our Gameplay character we control will reside along with any additional Blueprints that will belong specifically to the character object.

[IMAGE: 2.0_DataTypesFolder]

Now create the "DataTypes" folder under the "Blueprints" folder.  This is a special folder we will be using for blueprints that define the Data Assets we will be specializing for our combat system.

[IMAGE: 2.0_InterfacesFolder]

Now create the "Interfaces" folder under the "Blueprints" folder.  This is where the interfaces the four projects will all use will be stored.  Some projects will also have their own specialized interface functions that will be in their specific project subfolder.

[IMAGE: 2.0_PickupsFolder]

Now create the "Pickups" folder under "Blueprints".  This is where we will create our Pickup items that will give weapons to our character while playing.  It also will provide you with the understanding of how easy it can be to set weapons using the combat.

[IMAGE: 2.0_PlayerFolder]

Now create the "Player" folder under the "Blueprints" folder.  This is where we will hold any "Player" related blueprints, specifically the PlayerController.  This folder can also hold other player related info such as custom PlayerStates, but in our tutorials we will only be working with the PlayerController.  I leave the rest up to you for your own development.

2.1 Anim Blueprint

Before going too far we will duplicate the current animation blueprint for the Mannequin so we can work on with without disrupting the original ThirdPerson_AnimBP.

[IMAGE: 2.0_ThirdPerson_AnimBP]

Right click on the ThirdPerson_AnimBP and select "Duplicate".  Renamed the new Anim Blueprint to "ABP_DemoCharacter". That is all for now we will be coming back to this Anim Blueprint in the future to do some modifications.

2.2 Prepare the Skeleton

Now we will prepare our character's skeleton with the proper sockets so that we can attach and detach weapons to the hands and holster locations.

[IMAGE: 2.0_CreateCharacterBase]

Go to "Mannequin/Character/Meshes" and open up the "UE4_Mannequin_Skeleton".  We will be adding several new sockets to the Skeleton.

[IMAGE: 2.0_HandLBone]

Find the bone called "hand_l".  Right click on "hand_l" and select "Add Socket".

[IMAGE: 2.0_HandLBoneSocket]

This will create a socket with a name "hand_ISocket"  Select the socket and rename it to "s_OffHand".  This will be the off hand socket we use for weapons attached to the off hand.  I use the "s_" as my own personal naming scheme to indicate that this is a socket and not a bone.  Feel free to use what ever naming scheme you desire.

[IMAGE: 2.0_BoneProperties]

In the Details panel you can change the properties of this socket.  Here we'll be setting the Location and Rotation of the socket to the following properties.  As a special note, you can copy everything including the parentheses and just paste them into the properties.

hand_l
Socket Name: s_OffHand
Location: (X=9.500000,Y=-4.000000,Z=0.000000)
Rotation: (Pitch=0.000000,Yaw=90.000000,Roll=180.000000)

Repeat this process for the following Bones:

lowerarm_L
Socket Name: s_OffArm
Location: (X=25.000000,Y=0.000000,Z=15.000000)
Rotation: (Pitch=10.000000,Yaw=-180.000000,Roll=-90.000000)

hand_r
Socket Name: s_MainHand
Location: (X=-8.000000,Y=4.000000,Z=0.000000)
Rotation: (Pitch=3.000000,Yaw=60.000000,Roll=10.000000)

lowerarm_r
Socket Name: s_MainArm
Location: (X=-20.000000,Y=0.000000,Z=-9.000000)
Rotation: (Pitch=0.000000,Yaw=0.000000,Roll=0.000000)

spine_03
Socket Name: s_BackHolster
Location: (X=12.000000,Y=-0.500000,Z=0.000000)
Rotation: (Pitch=0.000000,Yaw=-3.000001,Roll=0.000000)

pelvis
Socket Name: s_RightSideHolster
Location: (X=7.000000,Y=0.000000,Z=20.000000)
Rotation: (Pitch=-80.000000,Yaw=180.000000,Roll=45.000000)

Socket Name: s_LeftSideHolster
Location: (X=7.000000,Y=0.000000,Z=-20.000000)
Rotation: (Pitch=-80.000000,Yaw=0.000000,Roll=-135.000000)

3.0 Add Core Classes

In this section we will add the Core classes we will need which will be leveraged by the other projects.  We will start with some basic UE4 classes that will be needed later.

[IMAGE: 3.0_CreateCharacterBase]

First lets create the base character we will be using for the game.  Go to the "DemoContent/Core/Blueprints/Character" folder and right click and choose to create a new Blueprint.  In the "All Classes" search block search for "ThirdPersonCharacter".  Click on the "ThirdPersonCharacter" class and click select.  Name the new blueprint "BP_DemoCharacterBase".

[IMAGE: 3.0_CreatePlayerController]

Go to "DemoContent/Core/Blueprints/Player" and create a new Player Controller.  Name it "BP_DemoPlayerController".

3.1 Weapon Objects

Next we will create our core managers and weapon actors.

[IMAGE: 3.0_CreateWeaponManager]

Under "DemoContent/Core/Blueprints/Character" right click and under "Create Basic Asset" select "Blueprints".  Under the "All Classes" section search for "PncsStandardWeaponManager".  We will be leveraging the "Standard Weapon Manager" because it is already setup to handle characters with two hands.

[IMAGE: 3.0_CreateWeaponActor]

Still under "DemoContent/Core/Blueprints/Character" right click and under "Create Basic Asset" select "Blueprints".  Under the "All Classes" section search for "PncsStandardWeaponActor".  We will be leveraging the "Standard Weapon Actor" because it has functions to easily determine it's weapon type.

3.2 Data Objects

We are now getting to get into the major parts of the combat system.  The Combat system runs on Data and we need to start defining what data we will be using for our combat system.  We will be creating the specialized data classes for our combat system.  This will include creating blueprints for our Weapon Data, Weapon Animation Data, Animation Set, the Weapon Manager, and the Weapon Actor.

[IMAGE: 3.0_CreateAnimationSet]

Go to "DemoContent/Core/Blueprints/DataTypes", right click and under "Create Basic Assets" select "Blueprints".  Under the "All Classes" section search for "PncsAnimationSetBase" and select it.  Name the new Blueprint "BP_DemoAnimationSet".  This blueprint object will hold all the animations we need for the currently equipped weapon.  The Animation system will leverage this object to play the specific weapon animations for the weapon and the Character Blueprint will leverage it to determine what Montages to play for attacking and blocking.

[IMAGE: 3.0_CreateWeaponData]

Still under "DemoContent/Core/Blueprints/DataTypes", right click and under "Create Basic Assets" select "Blueprints".  Under the "All Classes" section search for "PncsBaseWeaponData" and select it.  Name the new Blueprint "BP_DemoWeaponData". This blueprint object is a Data Asset referenced by the data table we created earlier.  This Data Asset will be loaded dynamically when needed to display weapons during game play.  It has the advantage of being asynchronously loaded so it does not cause your game to hitch or slow down.

[IMAGE: 3.0_CreateAnimationData]

Again under "DemoContent/Core/Blueprints/DataTypes", right click and under "Create Basic Assets" select "Blueprints".  Under the "All Classes" section search for "PncsBaseWeaponAnimationData" and select it.  Name the new Blueprint "BP_DemoWeaponAnimationData". This Data Asset's job is to hold all possible animations that a weapon could utilize.  For instance you may have different types of races in your game that use different sets of animations.  This Object would hold those animations as well.  All the default functions take the Actor as a parameter so that you can perform switches on their gender, race, or other criteria for your game and leverage different animations for each type of character.

[IMAGE: 3.0_CreateAnimationData]

4.0 Setup Data Service

Now we will setup the "Weapon Data Service". The Weapon Data Service is used by the Weapon Actors that represent your weapons in the game to load the appearance of the weapons.

This needs to be a globally accessible object and preferably one that is globally accessible in multiplayer games.  This limits our choices to: "GameInstance", "GameState", or the "GameSingletonClass".  Newer developers maybe tempted to use "GameMode", but if you are building a multiplayer game do not use this to hold your global game data.  The GameMode object does not exist on connected clients for multiplayer games, only the GameState.  For this demo we will use the "GameSingletonClass" as this is my preferred object to leverage for globally accessible data storage.

[IMAGE: 4.0_CreateDataTable]

Go to "DemoContent/Core/Data" and create a new DataTable by right clicking in the folder and selecting: "Miscellaneous/DataTable" from the menu.

[IMAGE: 4.0_CreateRowStructureSelection]

Now you need to select the PncsWeaponDataRow as the table structure to use.

[IMAGE: 4.0_NameWeaponTable]

Finally name the Weapon Table as" DT_WeaponData".  For now we are done fiddling with the Data Row and will come back to this table to fill it in later.

[IMAGE: 4.0_CreateBPGameDataService]

Now we will go to "DemoContent/Core/Blueprints/DataTypes" to create the GameSingleton Object.  Create a new UObject by right clicking and choosing to create a new blueprint.  In the "All Classes" list select "Object".  Name the new Blueprint "BP_GameDataService".

[IMAGE: 4.0_DataServiceClassSettings]

Open up the new BP_DataService blueprint.  Click on "Class Settings" at the top.  In the "Details" panel find "Interfaces".  Click the "Add" Drop down and type in "PncsWeaponDataService" to add that interface to this object.

[IMAGE: 4.0_DataTableVariable]

Now in the "MyBlueprint" panel go down until you see "Variables" and click the "+" button to add a new Variable.  Rename it to "WeaponDataTable" and make it a "DataTable" type.  Hit the Compile button.  Now Set the Default Value of the Table to the DT_WeaponData table we created earlier.

[IMAGE: 4.0_GetWeaponDataTable]

Now we will implement the IPncsWeaponDataTable function "GetWeaponDataTable".  This will simply return the "WeaponDataTable" variable we had created.

[IMAGE: 4.0_GetAmmoDataTable]

Finally we will implement the IPnjcsWeaponDataTable function "GetAmmoDataTable".  For this demo we will simply be using the same table for both data.  So return the "WeaponDataTable" variable.

4.1 Assign Game Singleton

Now we need to implement the GameSingleton Object in Unreal Engine.  This is a very simple step.

[IMAGE: 4.0_OpenProjectSettings]

Go up to "File" and select "Project Settings"

[IMAGE: 4.0_FindEngineGeneralSettings]

Scroll down to "Engine" and find "General Settings"

[IMAGE: 4.0_FindDefaultClasses]

Under "General Settings" scroll down to "Default Classes"

[IMAGE: 4.0_ExpandAdvanced]

Assign the BP_GameDataService object to the "Game Singleton Class".

5.0 Core Interfaces

Interfaces make your development life easier all around, casting to specific types in Unreal Engine can cause assets to load when they are not necessarily needed.  This is especially true when the object you are casting to is not of that type and can get messy when you need to cast to different types should a cast fail.  Interfaces are the proper way to handle the question "Is this object of type X and can I call function Y".  We will setup four Interfaces for our demo and they will not be the last.  They will represent the Core Interfaces that all 4 demo examples will leverage.  These interfaces are how we specialize the Combat System for any games need.

[IMAGE: 5.0_CreateInterface]

In the "DemoContent/Core/Blueprints/Interfaces" folder, right click and in the "Create Advanced Asset" list choose "blueprints" then select "Blueprint Interface".  Name the new interface "BPI_DemoAnimationData". 

[IMAGE: 5.0_CreateInterface]

Then create three other new interfaces and name them "BPI_DemoAnimationSet", "BPI_DemoCharacter", and "BPI_StandardWeaponActorData".

BPI_DemoCharacter represents the specialized functions for the character that the combat system will use.

BPI_DemoAnimationData represents the specialized functions we will use to fetch animations from the Animation Data Asset.  It is also used on the specialized UObject called the "Animation Set" which is a UObject designed to hold the current set of animations for a weapon which is leveraged by the Animation Blueprint and other systems.  We'll get more into the use and function of the "Animation Set" object later.

BPI_DemoAnimationSet represents the specialized functions we will use to "Set" animations to the current "Animation Set" object.  This will allow the Animation Set to blend weapon animations together based on your own logic so that you may have animations for a sword and shield configuration as well as a duel sword configuration.

BPI_StandardWeaponActorData is a specialization for Weapon Actors.  This interface leverages the "Standard" Enums to get and Set some properties of the APncsWeaponActor object.  This interface does not come standard with the Plugin simply because the plugin allows you to specify your own "Weapon Types" and Grip Types".  We'll discuss more on that later.

With the stubs of our Interfaces finished we'll come back to implement what interfaces we need later.

6.0 Define Weapon Data

In this section we will be defining what data we will be needing for our combat system.  This includes a weapon's visual appearance and the animations for that weapon.  There are two Data Assets that the combat system leverages for Weapons and Animations which we created stubs for earlier.  The first is the UPncsBaseWeaponData and the second is UPncsBaseWeaponAnimationData.  The information for weapons is stored in a DataAsset because it allows that data to be easily streamed in from disk asynchronously if it is not loaded thus making your game run faster and load faster overall.

The UPncsBaseWeaponData object is unique to each weapon, defining the visual properties of the weapon, how it will be positioned on the character, and any other properties you may want to add such as damage.  The UPncsBaseWeaponAnimationData is specifically meant to contain what animations need to be played for the weapon.  The Animation Data object is also meant to be a shared asset across multiple weapons because most swords in your game will likely use the same set of animations but could use different animations for daggers and great swords.  Each UPncsBaseWeaponData object has a reference to a UPncsBaseWeaponAnimationData object for easy loading and streaming.

Before we get into it lets take a moment to speak about an important concept of the Combat System.  Each weapon contains properties for "Weapon Type" and "Grip Type".  The Weapon Type is fairly straight forward it is an value indicating the type of weapon being represented.  As an Example the PNCS system comes with the EPncsStandardWeaponType that has the following values:

  1. Melee - weapon is a melee weapon
  2. Shield - weapon is a shield
  3. Ranged - weapon is a ranged weapon
  4. Ammo - object represents an ammo type.  Not really used by the weapon actor itself but for ammo supporting systems.

The Grip Type is used to indicate how the weapon is handled. For example the PNCS system comes with the EPncsStandardGripType that has the following values:

  1. One Handed - Weapon can be placed in the main hand or off hand
  2. Main Hand - Weapon can only be equipped to the main hand
  3. Off Hand - Weapon can only be equipped to the off hand
  4. Two Handed - No Off Hand weapon can be equipped as it requires both hands to wield.

Use of the EPncsStandardGripType and EPncsStandardWeaponType is completely optional as the Combat System allows you to define your own enum for weapon types and grip types.  The variables that represent these values are uint8 which is the type Unreal Engine uses for it's enums allowing you in blueprint to pass your custom enums into functions with little effort.

6.1 Setup Socket Types

While building the PNCS system I discovered a very useful method of defining how weapons attach to what socket in a configurable way on the UPncsBaseWeaponData object.  We'll define the Enum we need to do this and implement how the attachments work late when we build out our custom Weapon Manager.

[IMAGE: 6.0_DefineSocketType]

First we will create a custom Blueprint Enum for the sockets available for our weapons to attach to.  This allows us to configure how our weapons attach to holsters and hands much easier and without using FNames that can lead to future errors.  Right click in "DemoContent/Core/Blueprints/DataTypes" and under "Create Advanced Asset" choose "Blueprints" and "Enumeration".  Name this Enum "EDemoSocketTypes".

[IMAGE: 6.0_SocketTypeDisplay]

Create new Sockets by hitting the "New" button.  Create the following Enum Values and optionally descriptions:

  • None - Default No Socket Selected, Invalid
  • MainHand - Main Hand Socket
  • OffHand - Off Hand Socket
  • MainArm - Main Arm Socket
  • OffArm - Off Arm Socket
  • Back - Socket on the Back
  • RightHolster - Right side holster socket
  • LeftHolster - Left side holster socket

6.2 Setup Interfaces

We'll start by setting up the Weapon Data Interfaces as this plays a major role in defining the properties our weapon data will require.  All Weapon Actors have properties describing their "Grip Type" and "Weapon Type".

[IMAGE: 6.0_OpenStandardWeaponActorData]

Start by opening the BPI_StandardWeaponActorData Interface.  As noted before this interface will put on our Custom Weapon Actor.  The Weapon Actor will define a "Grip Type", "Weapon Type", "Socket Type", and "Power".

[IMAGE: 6.0_CreateWeaponActorInterfaceFunctions]

With the BPI_StandardWeaponActorData interface open click the "+" sign in the "functions" section.  Create the following functions with the category "BPI Standard Weapon Actor Data":

Function Name Input/Output Type Name
Get Grip Type  Output float GripType
   Test Description
       
GetWeaponType  Output EPncsStandardWeaponType WeaponType
       
GetSocketType Input EPncsStandardHandType handType
  Input bool isRelaxed
  Output EDemoSocketTypes SocketTypes
       
GetPower Output float Power

 We'll use this interface to fetch some useful info about our weapon.

[IMAGE: 6.0_CreateAnimationData]

Now open up the BPI_DemoAnimationData blueprint interface.  You'll need to create the following functions.

Function Name Input/Output Type Name
GetIdleAnimationSequence Output Anim Sequence Base Idle Sequence
       
GetMovementBlendSpace Output Blend Space Base Movement Blend Space
       
GetReadyCombatMontage Input EPncsStandardHandType Hand Type
  Output Anim Montage Base Ready Montage
       
GetRelaxCombatMontage Input EPncsStandardHandType Hand Type
  Output Anim Montage Base Relax Montage
       
GetJumpStartSequence Output Anim Sequence Base Jump Start
       
GetJumpLoopSequence Output Anim Sequence Base Jump Loop
       
GetJumpEndSequence Output Anim Sequence Base Jump End
       
GetAttackMontage Output Anim Montage Base Attack Montage
       
GetGuardMontage Output Anim Montage Base Guard Montage
       
GetDeflectionMontage Output Anim Montage Base Deflect Montage
       

Combat System Tutorials: Coming Soon

Coming Soon

Welcome to the Pro Networked Combat System Tutorials. Here you will find all tutorials associated with the Pro Networked Combat System (PNCS) Plugin for UE4

Basic Interaction System

A Basic Interaction System

Welcome to the somewhat final leg of the Mounting System Tutorial.  Here I will show you how to setup a very basic interaction system just so you can get started using the mounting system in your game, should you not have an interaction system of your own designed and developed.

Collision Setup

For our mounting system and our Interaction system we will be changing some of the UE4 default collision presets.  This will solve two problems.  The first is in its default state a mounted passenger’s camera will be blocked by the mount’s capsule and mesh components causing it to be trapped usually inside the mesh or center of the mount.  The Second is it will allow our visibility trace to hit the mesh component of our mount.

So there are other ways of doing this but for demonstration purposes this is the easiest way to do it.  You could create a whole new Preset just for your mounts, you could create a new Object Channel or Trace Channel.  But getting into the details of setting that up is beyond the scope of this tutorial and this plugin. It is very dependent upon the type of game you want to make.

Collision Panel
Fig 1 Collision Panel

Go to File / Project Settings.  Then go to Engine / Collision Settings.

Open the “Preset” tab.  The ones we will be most interested in are “Pawn” and “Character Mesh”.

Change Pawn Collision
Fig 2 Change Pawn Collision

Double click on the “Pawn” Preset and and change the Visibility and Camera settings to ignore.  That’s it, Now all objects with this collision preset will now ignore the Camera and Visibility trace types.  Why?  Because this preset is used for the capsule component and we want our whole character mesh to be what is interactable.  It will also prevent the camera for passengers from being stuck inside the mount capsule and allow it to freely rotate as normal.

Change Character Mesh Collision
Fig 3 Change Character Mesh Collision

Double click on “Character Mesh” preset.  We want to set it up as the image by setting the camera trace value to ignore.  This preset is used by the Character’s Mesh Component and will prevent the mount's mesh from interfering with passenger cameras.

Interface Setup

BPI Interactable Actor
Fig 4 Create BPI Interactable Actor

First thing we will do is create our interaction Interface.  In the MountingContent/Blueprints folder create a new Blueprint Interface and call it “BPI_InteractableActor”. This interface will be implemented by any actor in the game that can be interacted with.

Interact Interface Function
Fig 5 Interact Interface Function

The first function we will define is the “interact” function. By default UE4 should be asking you to enter a name for the function.  Call it “Interact” then set the value of the category to “BPI Interactable Actor” so that it appears organized in the actor that implements this interface. 

Give it an Actor input parameter.  Call it “InstigatingActor” this will be your player controller.  We could have the type for this be a Controller Type but I wanted to maximize the flexibility of this interaction system to fit with any game so this could be the player pawn, also thanks to the interfaces we do not need any specific function of the controller so an Actor will do.

Now give it an output of the boolean type and call it success.  This will return true if the interaction succeeded or false if it failed for any circumstance deemed appropriate by you.

Is Interactable Interface function
Fig 6 Is Interactable Interface function

This may seem silly but I personally love to add a simple “Is Interface Type” function to my Unreal Engine functions. The reason is by default these functions always return false.  So any object that does not implement this interface you can still call this function on and it will return false.  It’s a great little cheat for UE4 Blueprint Interfaces. 

Create a new function and call it “IsInteractable”.  Set it’s Category to “BPI Interactable Actor”.  Create a return variable and call it “IsInteractable”

And we are officially finished with our Interaction Interface.

Controller Setup

The primary functions of our interaction system will be held in our PlayerController.  I prefer to put such systems in the player controller because that allows us to customize the interaction systems differently for Players and AI.  Players tend to interact with things they are immediately focused on while the AI tends to need to collect data around them and then decide on what to interact with.

Blueprint Graphs
Fig 7 Blueprint Graphs

Open up the “BP_MountingPlayerController”.  First thing I always do is create an InputGraph.  I like to keep my graphs separate because they can become very cluttered very quickly.  If you separate the graphs into different purposes it makes things easier when working with a team.  Create a new Graph called “InputGraph” there should already be an “EventGraph” by default.  If it is not already there I highly suggest you create a third called “RpcGraph” that will hold our RPC events we will need to send to the server or client.

Create Focused Actor
Fig 8 Create Focus Actor

Now Create a new Variable of type Actor and name it “FocusedActor”.  This variable will be used to hold the current actor that our pawn is looking at.  

Create Function Stubs

Controller Function Stubs
Fig 9 Controller Function Stubs

We’ll begin by creating the subs for the functions we will need.  Begin by going to the functions panel and add a new function.  Call it “OnInteractionPressed”.  Then Create another one called “InteractWithFocusedActor” and finally “TraceForInteractable”.  Put these three functions into a category called “Interaction”.

Next create Two more function called “Dismount” and “Change Seats” and put it into a category called “Mounting”.

Interact With Focused Actor
Fig 10 Interact With Focused Actor

Double click to open the “InteractWithFocusedActor” function.  Create an input parameter of type AActor and call it “InteractableActor”

Change Seats
Fig 11 Change Seats

Create RpcFunctions

RPC Graph
Fig 12 RPC Graph

Double click on the RpcGraph and open it.  We will create three custom Events to support the mounting system.  In order to execute mounting, dismounting, and seat changing commands we need to send our functions to the server to start the process.

Create the first custom event and name it SERVER_InteractWithFocusedActor. Add a parameter of the Actor type and call it “InteractableActor”. Now Drag the “InteractWithFocusedActor” function we created under the “Interaction” category and connect the execution line to it.  Then connect the parameter.

Now create the Second custom event and name it “SERVER_Dismount”.  Drag the “Dismount” function we created under the “Mounting” category into the graph and connect it to the SERVER_Dismount function.

Now create the Third custom event and name it “SERVER_ChangeSeats”.  Create an input variable called “Seat Index”.  Drag the “ChangeSeats function we created under the “Mounting” category into the graph and connect it to the SERVER_ChangeSeats execution line.  Connect the SeatIndex parameter to the “NewSeatId” of ChangeSeats function.

Server Interact With Focused Actor
Fig 13 Server Interact With Focused Actor

Select “SERVER_InteractWithFocusedActor” event.  In the details panel set the “replicates” property to “Run On Server” and then check the “Reliable” flag.  In a real game you'll want to do some kind of validation here that the player is within interactable range or something along those lines.  You could also have the trace be executable on the server but depending on how accurate your rotations are between the client and server that could cause more frustration than happy players.

Do the same for “SERVER_Dismount” and “SERVER_ChangeSeats”

Implement TraceForInteractable

We will now implement the TraceForInteractable function.  For Sanity sake I’m simply going to link the code from BlueprintUE rather than attempt to create a picture for it all.

Blueprint UI: Trace for Interactable

Trace For Interactables Ouputs
Fig 14 Trace For Interactables Ouputs

We want to return true or false if we succeed in hitting something or fail in hitting something.  So we’ll create an output variable for the “TraceForInteractable” function.

In brevity this function checks if the character is currently mounted. 

TFI Line Trace
Fig 15 TFI Line Trace

If it is not mounted it performs a line trace by the visibility channel.  It first gets the current pawns location and adds 90 units on the Z axis to simulate the location of the eyes of the character.  As the blueprint explains this can be different from pawn to pawn but adjusting this is outside the scope of this tutorial.  This value gets set as the Starting point of the line trace.  Then we get the rotation of the controller and transform that into a forward unit vector.  It multiplies that unit vector by 300 units giving it a length of 300.  Finally we add that to the start position of the trace to get the end point of the line.

TFI Is Itneractable
Fig 16 TFI Is Interactable

We then check if the line trace hit something.  If it did we retrieve the hit actor and call the BPI_InteractableActor function “IsInteractable”.  If this is an interactable actor than it will return true, so long as we implement this function to do so.

TFI Return Values
Fig 17 TFI Return Values

If we have detected an interactable actor than we set it to the “FocusedActor” variable we setup earlier.  If we do not detect an actor then we clear the “FocusedActor” variable.

TFI Clear Values
Fig 18 TFI Clear Values

Going back to the test for if the current pawn is mounted.  On the True Execution line we we want to make sure that we currently have no FocusActor Referenced.  So we use a Validated Get to test if it has a reference to something and if it does we clear that reference, other wise we return false.

Implement OnInteractionPressed

We will now implement the OnInteractionPressed function.  A link to copy and paste the code from BlueprintUE is available.

Blueprint UI: On Interaction Pressed

OIP Is Mounted
Fig 19 OIP Is Mounted

We’ll briefly go over how this function works.  First we determine if our character is currently mounted or not.

OIP Interact with focused actor
Fig 20 OIP Interact with focused actor

If we are not currently mounted than the false execution branch tests if we currently have a “focused actor”.  If we do have a focused actor than we simply pass it through to the “InteractWithFocusedActor” function and return success.  If we do not have a focused actor than we return false.

OIP Is Seated On Mount
Fig 21 OIP Is Seated On Mount

If we are currently mounted than the true execution branch gets the Current Character Pawn and tests if it is fully seated on the mount. 

OIP Returns
Fig 22 OIP Returns

If we are not seated on the mount than we invalidate the input and ignore it.  If we are seated on the mount than we call the “Dismount” function we created under the Mounting category and return true.

Implement InteractWithFocusedActor

Now we implement the InteractWithFocusedActor function.  A link to copy and paste the content of this function is available via BlueprintUE:

Blueprint UI: Interact With Focused Actor

Interact with Focused Actor
Fig 23 Interact With Focused Actor

Start checking that the supplied parameter “InteractableActor” is valid.  Then use the build in UE4 BP macro “Switch Has Authority”.  If this is the Authority Than we want to call the BPI_InteractableActor function “Interact” which will have the (Message) text text to it.  We want the “target” of that function to be the “InteractableActor” which should be our potential mount.  Then we want the “Instigating Actor” to be our controller, which we’ll pass a reference to “self” in.

If this is not the Authority then we want to call our Server function “SERVER_InteractWithFocusedActor” and we’ll pass our desired focused actor into it as a parameter up to the server.  When “SERVER_InteractWithFocusedActor” is called on the server it will simply call this function but because it is already on the authority it will pass through to the Interact logic in the Authority execution line.

Implement Dismount

Now we will implement the Dismount function.  A link to copy and paste the content of this function is available through BlueprintUE in the link below.

Blueprint UI: Dismount

Dismount
Fig 24 Dismount

First thing we do is check that we are on the Authority.  If so than we Get the CharacterMount and check that it is valid.  If the character mount is valid we call the controllers “PrepareToDismount” function and pass the retrieved mount into it as a parameter.  Finally return the result of the PrepareToDismount function.

If this is not the authority than we want to call our “SERVER_Dismount” function and return false.  When SERVER_Dismount is called on the server it will execute the Dismount function and take the authority execution line.

Implement Change Seats

Now we will implement the Change Seats function. A link to copy and paste the content of this function is now available through BlueprintUE in the link below.

Blueprint UI: Change Seats

Change Seats
Fig 25 Chnage Seats

First thing we do is check that we are mounted, and if we are not than we ignore this action and return false.

Next we detect if we are on the authority or not.  If  this is the authority than we check we have a valid mount.  If we do then we check that the desired seat we want to move to is not occupied.  If the seat is not occupied than we get our character pawn, get the MountRiderComponent, and then call the component’s ChangeSeatById, sending in the “NewSeatId” parameter to “SeatId”

If any of the validity checks fail we simply return false.

If we are not on the authority than this function calls “SERVER_ChangeSeats” on the server.

Execute Interactions

Trace Each Tick
Fig 26 Trace Each Tick

In the Event Graph we will call our TraceForInteractable on tick as shown in the image.  For demonstration purposes I’m not going to bother adding any optimizations such as not doing this on the server.

E Key for Interaction
Fig 27 E Key for Interaction

Go to the input graph and in there right click and search for the “E Key”.  If you already have an Input Setup for this by all means use that but again for demonstration i’m going to hard wire this to E.  From the “Pressed” execution line drag it out and call “OnInteractionPressed”.

Seat Key Input
Fig 28 Seat Key Input

We will bind the number 1 and 2 keys to our seat changing functions.  We will set the 1 key to be our driver seat change and the 2 key to be our passenger seat change.  This setup is easily expanded to more seats.

Controller Completed

That is it we are finished with the controller.  On tick it will scan wherever the player is currently looking.  If they have a valid interactable in their sights by pressing E they will trigger the interaction process for it.

Setup the Mount

Now we must set up our Mount for interaction.  Open up your mount, in this tutorial I am using the “BP_Horse”.

Mount Class Settings
Fig 29 Mount Class Settings

We want to add our “BPI_InteractableActor” interface to our mount. 

Press the “Add” button in the Interfaces list on the details panel and find our “BPI_InteractableActor” interface.

Blueprint UE: Interact Function

Interact Function
Fig 30 Interact Function

Now under the Interfaces list in the Blueprint Panel expand “BPI Interactable Actor”.  Double click on “Interact” function.

We will implement this very simply.  For our interaction system the Instigating actor is our controller.  But since this is an generic interaction system we do not know this for sure so we’ll call “GetCharacterControlller” from the instigating actor.  Now that we know we have a controller we’ll check that it is a Valid object.  Finally we will call “PrepareToMount” as a function message with the target set to the Controller and the “Mount or Rider” parameter set to “self” which is our mount.  Then we return true for success.

Is Interactable
Fig 31 Is Interactable

Now implement the IsInteractable function.  We are simply going to return true for this function.  Though you could set up any bit of logic you want such as setting this to false if the mount is full.

Finished

Well that is it, our interaction system for mounting is setup and ready to go.  You can now run the game and interact with your mount and ride it around.

Mounting System Animations (WIP)

Warning

This document is currently a work in progress (WIP).  It's a lot of text and not a whole lot of demonstration.  Over time I plan to improve that but for now I just need it to get out the door.

Developing Animations for the Mounting System.

For your single player game with absolutely (zero, zilch, nada) no plans of expanding the game with multiplayer features in the future, then any animations will work fine for mounting and dismounting be they with root motion or without.  However if your game is to be a Multiplayer game then you have some serious considerations to make.  Unreal Engine is a powerful engine that supports both Root Motion Animations and fully Networked Game play but it does not do these things very well at the same time. 

If you do not want to read this article there is a 5 minute video I made a while back that sort of explains the main problem.  Check out the Additional Resources Link at the bottom.

Common Problems with Networked games and Root Motion

I personally have hit two common problems that persist as of UE 4.25, and again this is not an issue with the Plugin but an issue with Unreal Engine itself.  The First is  “The Montage Play Speed” Problem and is the most obvious.  The Second is what I call the “Lag Offset Problem” and is much more insidious.  Both of these problems arise with connected clients, any one playing as a Listen Server will not observe them but any connected players will experience them.  You may be able to remedy these by temporarily turning off Movement Replication during these montage sequences and/or disabling root motion on only the client but with out considerable additional development these problems still persist.

The Montage Play Speed problem occurs with any root motion animation played on a client.  For reasons unknown to myself the play rate of any animation with root motion at least double the normal play rate.  This includes all animations including sequences, montages, blend spaces, etc.  You can do some code hackery to check if the animation is playing on a connected client and attempt to slow it down, but that in of itself can be tricky and does not always work. I have also attempted triggering the Montage to play only on the server but then it does not play at all on the client.

The “Lag Offset Problem” occurs at a very specific circumstance.  Part of the mounting system’s functionality is to allow developers to play an animation to start mounting and start dismounting.  At the end of those animations the system attaches the character’s capsule to the mount or detaches it from the mount.  I make no assumptions on the things you want to do with this plugin and so I leave it up to you, the developer, whether you want to allow riders to attach or detach while the mount is moving and that movement often is the cause of the Lag Offset Problem.  A very interesting phenomenon occurs when you add movement into this equation of Networked Gameplay plus Root Motion Animations plus character attachment.  The player’s capsule is offset proportionally to the amount of lag between the client and the server, meaning the bigger the lag the more the character will float off of their intended seat on clients and it is in the direction of the movement.

So these are two of the issues you will need to handle if you are wanting to deal with Root Motion Animations in a Networked game.  For now these are outside the scope of this plugin, that may change in the future as the engine continues to improve.  And the main reason why it is not a priority of the mounting system is because there are ways around this problem for networked games by creating your animations slightly differently for mounting and dismounting that do not leverage Root Motion.

Mounting Animations for Networked Games

In all honesty I would suggest not having any animations for online games when it comes to getting on or off mounts.  Root Motioned Animations cause the greatest amount of trouble and scripted motion animations will look the best but require the most work.

Scripting the animation usually requires that designers and programmers (either blueprints or C++) work on building out a sequence of moving the capsule and playing animations at the same time using customized curves and timing systems and handling UE4’s move replication.  Unfortunately this is beyond the scope of this document.  Basically if you got good programmers and good artists on your team you should be able to figure this out.

What I will talk about is specialized animations which only require that the artist build the animations a certain way to produce a decent mounting and dismounting effect.  I am sure a talented technical artist can hammer out the details far better than what I will present but it should get you most of the way there.

Building Specialized Animations

The animations provided in the Demo Project are built using this methodology.  There are a few key things to note.  The main thing is you will need to build the animations based on the structural makeup of the Pawn or more specifically the Character Object that represents the Rider. 

For instance all ACharacter Objects have a capsule that represents the root component.  It is the root component (usually the capsule unless you have a custom pawn) that gets attached to the mount or vehicle, not the character mesh.  As an artist you may be tempted to build animations based on the root of the character model, usually that is located at the feet.  Instead you need to build the animations according to the midpoint of the capsule that will surround the character and be attached to the mount. 

This usually means you’ll need to shift your character down below the floor grid to compensate for the differences.  I tend to build the sitting on mount animation first then work backwards from there.  That way I know how the character is supposed to look while on the mount and about where.

Finally on the imported animations you want to set blend in and blend out to be Zero.

(Images to come, for demonstration see Video)

Additional Resources

My Video on Building Animations for Networked Mounting.  Yes it is an older video but still relevant.
https://www.youtube.com/watch?v=KIZP3kkomSs&list=PLK-uozTlWMkysM9B9unrrWSTrhoWhrakk&index=6

Root Motion Over Network discussion on UE4 Forums.  This provides a few additional methods to accomplishing root motion over the network but be warned none of it is easy.
https://forums.unrealengine.com/development-discussion/animation/97130-root-motion-over-network-how-its-done

Redit: Root Motion in Multiplayer:
https://www.reddit.com/r/unrealengine/comments/8j6ova/root_motion_in_multiplayer/

This is a general Root Motion or Scripted Motion Video for anyone interested in the differences and why you would want to use one over the other.
https://www.youtube.com/watch?v=j7XZ3Q8JNfM

A VERY good tutorial on how to setup a Full Root Motion Animation System but it only works well in Single player games:
https://www.youtube.com/watch?v=QCA4ZQzFZ9s&list=PL8xcKsKsXEfvKkHFIEwfrkAxz0wq6ykPm&index=1

Mounting System Tutorials

Welcome to the Pro Mounting System Tutorials. Here you will find all tutorials associated with the Pro Mounting System Plugin for UE4