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 and ship it.  For this reason the PNCS system is very robust system and the totality of the tutorials on how to use it 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 all the animations required that are already setup and ready to go.  There will be a separate animation tutorial to go over how these are setup.

Get the plugin at: UE4 Marketplace - Pro Networked Combat System

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. 

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

First demo focuses 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 second demo in the series will 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 third demo 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 fourth demo 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

1.1 Templates and Content

1.2 The Common folder

2.0 Basic Setup

2.1 Anim Blueprint

2.2 Prepare the Skeleton

3.0 Add Core Classes

3.1 Weapon Objects

3.2 Data Objects

4.0 Setup Data Service

4.1 Assign Game Singleton

5.0 Create Interfaces

6.0 Define Weapon Data Interfaces

6.1 The Standard Weapon Actor Data Interface

6.2 Demo Animation Data Interface

6.3 Demo Animation Set Interface

7.0 Define Weapon Data

7.1 Setup Socket Types

7.2 Demo Weapon Data

7.2.1 Setup Weapon Variables

7.2.2 Implement Standard Weapon Actor Data Interface

7.3 Demo Animation Data

7.3.1 Setup Animation Variables

7.3.2 Implement Combat Demo Animation Interface

7.4 Demo Animation Set

7.4.1 Setup Animation Set Variables

7.4.2 Implement Demo Animation Data Interface

7.4.3 Implement Demo Animation Set Interface

8.0 Setup Weapon Actor

9.0 Setup Weapon Manager

9.1 Utility Functions

9.1.1 Get Socket Name From Enum

9.1.2 Get Weapon Animation Data

9.1.3 Create Execution Macro

9.2 Override Functions

9.2.1 Override Get Current Weapon Socket

9.2.2 Override Update Animation Set

10.0 Setup Character Interface

11.0 Setup Base Demo Character

11.1 Interfaces and Components

11.2 Setup Variables

11.3 Setup Custom Functions

11.4 Implement Unified Controller Pawn Interface

11.5 Implement Weapon Owner Interface

11.5.1 General Functions

11.5.2 Trace Functions

11.5.3 Targets Functions

11.5.4 Animation Functions

11.6 Implement BPI Demo Character

11.6.1 States

11.6.2 Stats

11.6.3 Animations

12.0 Player Controller

12.1 Implement Unified Controller Pawn

13.0 Animation Blueprint

13.1 Setup Variables

13.1.1 References

13.1.2 State

13.1.3 Default Anims

13.1.4 Active Anims

13.2 Setup Functions

13.3 Event Graph

13.4 Anim Graph Location

13.5 Anim Graph Montage Blending

14.0 Outro


The Combat Design

Before we begin we need to establish what the design of our combat system will look like.  This is the first step you should take when developing your combat system.  We will establish a few rules and some of the systems behind that.

  1. Action Adventure style combat system
  2. Tutorial itself must be short but display the robustness of the Combat System
  3. Using two hands for weapons; a main hand and a off hand.
  4. Will include Unarmed, Melee, and Bow Attacks
  5. Will use very simple combos.
  6. Will be able to block with any weapon
  7. Unarmed and Melee attacks will have two attack animations for swing left and swing right.
  8. Bows will have 1 attack animation and will be executed with a simple button push
  9. Blocks will cause a deflection of an attack and stun the attacker
  10. We will only deal with main hand weapons, dual wielding will not be implemented.
  11. Ranged Weapons will always be in the main hand.
  12. Ammo will be universal

For a bit of an explanation.  The First requirement is that we are making an Action Adventure style combat system; think games like Zelda and Monster Hunter. 

Next the second requirements is to keep this tutorial as short as possible while trying to impart the robustness and features of the combat system can bring meaning this will be a fairly slimmed down combat system than what you may implement for an Action Adventure Game.  As a fair warning this combat system is meant to be a professional grade system applicable for any combat system regardless of the type of game you are building.  In general I am not just building this combat system for the UE4 market place, but as an integral part of my future game development needs.  This is also why the combat system is not a plug an play system, but requires a considerable amount of configuration to which I will guide you through as efficiently as possible.  As time goes on the final project will be built out with different combat system demonstrations that you can leverage in your games as a sort of quick implementation using the migration tools of UE4.

So the combat system we will be designing will leverage unarmed punches, sword slashes, and Bow weapons.  Unarmed and melee/swords will have two attacks; unarmed will have a right hand swing and a left hand swing while swords will have a left slash and a right slash.  Bows will be quick firing meaning you push the button and the character fires the bow (no holding down and releasing).

The combat system will utilize a very simple combo system to track if it should be performing a left or right swing/slash attack.  It will start at 0 indicating no current combo and increment to 1 and then 2.  Then after 2 it will reset to 1 and continue to toggle between 1 and 2.  Once a certain amount of time has lapsed it will reset completely to 0.  In general 0 and 2 will indicate the first attack and 1 will be the second attack.

All weapons save the bow will have a guard mechanic.  Attacks that hit a guarding character will be deflected.  While we will implement a shield weapon it will behave no differently than the basic blocking unarmed will have for the tutorial demo at least.  In the final project as more demos come out you will have improved examples that refine the mechanics of this system.

We will not leverage a dual weapon combat system in this tutorial.  As indicated above we will also not be leveraging a hold-to-draw and release firing system for the Bow.  However in time I plan to make additional combat system demonstrations that will utilize these systems so you can look to see how they are implemented as the Final Demo Project is updated over time.  However a lot of how we will be setting up these demos will be applicable to setting up these later additions we will not cover with a little creativity and know-how.

We will not track different types of ammo but will leverage a universal ammo.  We will implement the basic methods of setting ammo, checking ammo, and consuming ammo.


1.0 Project Tour

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

Blueprint Tutorials
Fig 1.0 Blueprint 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

Third PersonBP Folder
Fig 1.1.1 Third Person BP Folder

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.

Other Important Content Folders
Fig 1.1.2 Other Important Content Folders

 I always leverage 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.  Finally I have a custom "ExampleContent" folder that will

1.2 The Common Folder

The Common Folder
Fig 1.2.1 The 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.

The Props Folder
Fig 1.2.2 The 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.

The Animations Folder
Fig 1.2.2 The Animations 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

Back to Top


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.

Demo Content Folder
Fig 2.0.1 Demo Content Folder

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

Core Folder
Fig 2.0.2 Core Folder

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.

Blueprints Folder
Fig 2.0.3 Blueprints Folder

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.

Data Folder
Fig 2.0.4 Data Folder

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

Character Folder
Fig 2.0.5 Character Folder

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.

Data Types Folder
Fig 2.0.6 Data Types Folder

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.

Interfaces Folder
Fig 2.0.7 Interfaces Folder

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.

Pickups Folder
Fig 2.0.8 Pickups Folder

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.

Player Folder
Fig 2.0.8 Player Folder

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.

Third Person Animation Blueprint
Fig 2.1.1 Third Person Animation Blueprint

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.

Mannequin Skeleton
Fig 2.2.1 Mannequin Skeleton

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

Left Hand Bone
Fig 2.2.2 Left Hand Bone

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

Off Hand Socket
Fig 2.2.3 Off Hand Socket

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.

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)

Back to Top


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.

Create the Demo Character Base Blueprint
Fig 3.0.1 Create the Demo Character Base Blueprint

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

Create the Demo Character Controller Blueprint
Fig 3.0.2 Create the Demo Character Controller Blueprint

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.

Create the Demo Weapon Manager Blueprint
Fig 3.1.1 Create the Demo Weapon Manager Blueprint

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.

Create the Demo Weapon Actor Blueprint
Fig 3.1.2 Create the Demo Weapon Actor Blueprint

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.

Create the Animation Set Blueprint
Fig 3.2.1 Create the Animation Set Blueprint

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.

Create the Weapon Data Blueprint
Fig 3.2.1 Create the Weapon Data Blueprint

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.

Create the Weapon Animation Data Blueprint
Fig 3.2.1 Create the Weapon Animation Data Blueprint

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.

Back to Top


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.

Create Data Table
Fig 4.0.1 Create Data Table

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

Select Table Data Structure
Fig 4.0.2 Select Table Data Structure

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

Name the Data Table
Fig 4.0.3 Name the Data Table

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.

Create Data Service Object
Fig 4.0.4 Create Data Service Object

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

Class Settings and Interfaces
Fig 4.0.5 Class Settings and Interfaces

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.

Add Data Table Variable
Fig 4.0.6 Add Data Table Variable

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.

Implement Get Weapon Data Table
Fig 4.0.7 Implement Get Weapon Data Table

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

Implement Get Ammo Data Table
Fig 4.0.8 Implement Get Ammo Data Table

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.

Open Project Settings
Fig 4.1.1 Open Project Settings

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

Find General Settings
Fig 4.1.2 Find General Settings

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

Find Default Classes
Fig 4.1.3 Find General Settings

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

Assign Game Data Service
Fig 4.1.4 Assign Game Data Service

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

Back to Top


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

Create New Interface
Fig 5.0.1 Create Interface

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

Demo Character Interface
Fig 5.0.2 Demo Character Interface

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.

All Interfaces
Fig 5.0.3 All Interfaces

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

Back to Top


6.0 Define Weapon Data Interfaces

In this section we will layout the interfaces that our Weapon's Data Systems will leverage to pull information from the Data Assets and load into the Weapon Actors and the Animation Sets.

6.1 The Standard Weapon Actor Data  Interface

We'll start with the Weapon Actor Data.

Open Weapon Actor Data Interface
Fig 6.1.1 Open Weapon Actor Data Interface

Open the BPI_StandardWeaponActorData Interface.  This interface will be implemented on the BP_DemoWeaponData object and used by the BP_DemoWeaponActor object to retrieve information about the currently set weapon.

Setup Weapon Actor Data Interface
Fig 6.1.2 Setup Weapon Actor Data Interface

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".  This interface will be implemented on our BP_DemoWeaponData object so that our weapon actor can fetch the relevant data from the data asset.

Function Name Input/Output Type Name
Get Grip Type  Output EPncsStandardGripType GripType
  Get the Grip Type the weapon will use, this influences how the weapon is equipped such as a One Handed, Main Hand, Off Hand, Two Handed, etc.
       
GetWeaponType  Output EPncsStandardWeaponType WeaponType
  Get the Weapon Type the weapon will represent such as a Melee, Ranged, or Shield weapon. 
       
GetSocketType Input EPncsStandardHandType handType
  Input bool isRelaxed
  Output EDemoSocketTypes SocketTypes
  Get the socket the weapon should attach to based on the the parameters for the desired hand type and if the character is currently relaxed or ready for combat.
       
GetPower Output float Power
  Get the Power rating of the weapon, this will act as our Damage Rating. 

Back to Top

6.2 Demo Animation Data Interface

Open Weapon Animation Data Interface
Fig 6.2.1 Open Weapon Animation Data Interface

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

Setup Weapon Animation Data Interface
Fig 6.2.2 Setup Weapon Animation Data Interface

This interface will be implemented on the BP_DemoAnimationData and the BP_DemoAnimationSet object we created and allow the combat system to query animations from these objects.

Function Name Input/Output Type Name
GetIdleSequence Output Anim Sequence Base Idle Sequence
  Get the Idle Animation to play when the weapon is equipped
       
GetMovementBlendSpace Output Blend Space Base Movement Blend Space
  Get the Movement Blendspace to Play when the weapon is equipped
       
GetReadyCombatMontage Input EPncsStandardHandType Hand Type
  Output Anim Montage Base Ready Montage
  Get the Ready Montage for the weapon based on the HandType supplied.
       
GetRelaxCombatMontage Input EPncsStandardHandType Hand Type
  Output Anim Montage Base Relax Montage
  Get the Relax Montage for the weapon based on the HandType supplied
       
GetJumpStartSequence Output Anim Sequence Base Jump Start
  Get the Jump Start Animation Sequence that will play when the weapon is equipped.  
       
GetJumpLoopSequence Output Anim Sequence Base Jump Loop
  Get the Jump Loop Animation Sequence that will play when the weapon is equipped.  
       
GetJumpEndSequence Output Anim Sequence Base Jump End
  Get the Jump End Animation Sequence that will play when the weapon is equipped.  
       
GetAttackMontage Output Anim Montage Base Attack Montage
  Get the Jump Start Animation Sequence that will play when the weapon is equipped.  
       
GetGuardMontage Output Anim Montage Base Guard Montage
  Get the Guard Montage to play when the weapon is equipped.  
       
GetDeflectionMontage Output Anim Montage Base Deflect Montage
  Get the Deflection Montage to play when the weapon is equipped.  
       
Has Off Hand Animations Output bool Has Animations
  Get Bool indicating that the Animation Data Has Off Hand Animations  
       

 Back to Top

6.3 Demo Animation Set Interface

Open Animation Set Interface
Fig 6.2.1 Open Animation Set Interface

`

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

Setup Animation Set Interface
Fig 6.2.2 Setup Animation Set Interface

`

This interface will be implemented on the BP_DemoAnimationSet object so that the available animation properties can be swapped out when new weapons are equipped.

Function Name Input/Output Type Name
SetIdleSequence Input Anim Sequence Base In Idle Sequence
  Output Anim Sequence Base out Idle Sequence
  Sets the current Idle Animation Sequence to use.
       
SetMovementBlendSpace Output Blend Space Base In Movement Blend Space
  Output Blend Space Base Out Movement Blend Space
  Set the current movement blendspace to use for the animation system.
       
SetReadyCombatMontage Input EPncsStandardHandType Hand Type
  Input Anim Montage Base In Ready Montage
  Output Anim Montage Base Out Ready Montage
  Set the current Ready Anim Montage to play for the specified weapon hand.
       
SetRelaxCombatMontage Input EPncsStandardHandType Hand Type
  Input Anim Montage Base In Relax Montage
  Output Anim Montage Base Out Relax Montage
  Set the current Relax Anim Montage to use for the specified weapon hand.
       
SetJumpStartSequence Input In Anim Sequence Base Jump Start
  Output Anim Sequence Base Out Jump Start
  Set the Jump Start Animation Sequence to play for the current animation set  
       
SetJumpLoopSequence Input In Anim Sequence Base Jump Loop
  Output Anim Sequence Base Out Jump Loop
  Set the Jump Loop Animation Sequence that will play for the current animation set.  
       
SetJumpEndSequence Input Anim Sequence Base In Jump End
  Output Anim Sequence Base Out Jump End
  Set the Jump End Animation Sequence for the current animation set.  
       
SetAttackMontage Input Anim Montage Base Out Attack Montage
  Output Anim Montage Base Out Attack Montage
  Set the Jump Start Animation Sequence that will play for the current animaiton set.  
       
SetGuardMontage Input Anim Montage Base In Guard Montage
  Output Anim Montage Base Out Guard Montage
  Get the Guard Montage to play when the weapon is equipped.  
       
SetDeflectionMontage Input Anim Montage Base In Deflect Montage
  Output Anim Montage Base Out Deflect Montage
  Get the Deflection Montage to play when the weapon is equipped.  
       

 Back to Top


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

Back to Top

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

Create Enum
Fig 7.1.1 Create Enum

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

Setup the Sockets Enumeration
Fig 7.1.2 Setup the Sockets Enumeration

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

Back to Top

7.2 Demo Weapon Data

Now we will define our Demo Weapon Data. This data object will be held as a soft reference in the DT_WeaponData table we created earlier.  Our Weapon Actors will then Asycronously load that data and display the visual aspects of the weapons when finished loading.

Open Weapon Data Blueprint
Fig 7.2.0.1 Open Weapon Data Blueprint

First open up the BP_DemoWeaponData found in "DemoContent/Core/Blueprints/DataTypes".

Add Interfaces
Fig 7.2.0.2 Add Interfaces

Next select "Class Settings" and under the interfaces tab click the "Add" Button.  Search for "BPI Standard Weapon Actor Data" and select it.

7.2.1 Setup Weapon Variables

Next we'll add the variable's we will need to configure our DemoWeaponData objects.  Under the Variable's section of "My Blueprint" click the "+" icon to create the following variables. To keep things organized I used the categories of "Weapon", "VFX", and "Sockets".

Setup Weapon Variables
Fig 7.2.1.1 Setup Weapon Variables

The following variables where created using the "Weapon" category.

Property Name Type Default
 Grip Type  EPncsStandardGripType  None
  Represents the type of Grip the weapon will have.
 
WeaponType EPncsStandardWeaponType None
  Represents the type of Weapon
 
Power float 0.0
  This will represent the attack power of our weapon.
 

These variables where created using the "VFX" category.

Property Name Type Default
Mesh Data PNCS Weapon Mesh Data Defaults
  Used to store the Mesh to use for the weapon. Also the Grip and Holster transforms for when the weapon is attached.
 

These variables where created using the "Sockets" category.

Property Name Type Default
MainHandSocket EDemoSocketTypes None
  Socket to use when in ready mode and equipped to the main hand
 
OffHandSocket EDemoSocketTypes None
  Socket to use when in ready mode and equipped to the off hand
 
MainHolsterSocket EDemoSocketTypes None
  Socket to use when in relax mode and equipped to the main hand.
 
OffHandSocket EDemoSocketTypes None
  Socket to use when in relax mode and equipped to the off hand
 

Back to Top

7.2.2 Implement Standard Weapon Actor Data Interface

Finally we will implement our custom "BPI_StandardWeaponActorData" interface we created earlier.

Expand the Interfaces Section
Fig 7.2.1.1 Expand the Interfaces Section

Under the "My Blueprint" panel expand the "Interfaces" section.

Implement Get Power
Fig 7.2.2.2 Implement Get Power

Double click on the function "Get Power" and implement it by dragging the "power" variable into the output "power".

Implement Get Socket Type
Fig 7.2.2.3 Implement Get Socket Type

Implement this by using a switch for the type "EPncsStandardHandType" to switch between "Main Hand" and "Off Hand" values.  If it is an invalid setting we will assume it is the main hand, though you can handle this logic anyway you see fit. 

We will branch for if we are dealing with Relaxed or Ready which is a supplied variable. 

For the Main Hand we return the "Main Holster Socket" if we are in the relaxed state and "Main Hand Socket" if we are in the ready state. We do something similar for the off hand.  If it is in the relaxed state we return "Off Holster Socket" and if it is in the ready state we return "Off Hand Socket".

As you can see this will be leveraged by our Weapon Manager to determine what socket the weapon actors should be attached to when in ready or relaxed mode.  If in your game you never have your character in a ready state or relaxed state then you can simply return the same socket name.  For games where the hand the weapon is in is always the same you can simply ignore designing a function like this at all and simply return the same socket name in the Weapon Manager that we later implement.  This is to show how flexible the weapon system can be in allowing you to design the way it works.

Implement Get Weapon Type
Fig 7.2.2.4 Implement Get Weapon Type

Implement this function by dragging the "WeaponType" variable into the "Weapon Type" output parameter.

Implement Get Grip Type
Fig 7.2.2.5 Implement Get Grip Type

Implement this function by dragging the "Grip Type" variable into the "Grip Type" output parameter.

This wraps up all the info we will need for our DemoWeaponData object.  Later we'll create a Data Asset for this type and fill it out for our Unarmed, Sword, and Bow weapons.  In later tutorial we'll create a new Data Asset for Ammo which will load the type of ammo pouch, magazine, or quiver onto the character to a specific socket and how to implement that.

7.3 Demo Animation Data

The Demo Animation Data is another Data Asset that is meant to hold the Animations for a given weapon.  Our simple weapon system will we are developing will only hold a small set of animations but you can design your own combat system to hold many animations for different purposes.  For instance Dual Wielding weapons may use a different set of animations than if they where single handed, or if you have different races in your game Elves may have a different fighting style than Humans, Orcs, and Dwarves.  This allows you to design how your combat system with your specifications rather than my own idea of how you should do it.

Open the Weapon Animation Blueprint
Fig 7.3.0.1 Open the Weapon Animation Blueprint

First open up the BP_DemoWeaponAnimation blueprint found in "DemoContent/Core/Blueprints/DataTypes".

Add Interfaces
Fig 7.3.0.2 Add Interfaces

Next select "Class Settings" and under the "Interfaces" tab click the "Add" Button.  Search for "BPI_DemoAnimationData" and select it.

Back to Top

7.3.1 Setup Animation Variables

 Now it's time to setup the variables we will need for the Animation Set. These will indicate the current "set" of animations that the character can use for animations with the current weapons it has equipped. Notice that I have named each variable according to the type of animation it represents. For examples Montages all end with "Montage" and Blendspace ends in "BlendSpace".

Add Variables
Fig 7.3.1.1 Add Variables

We'll start with movement animations which will be created in the "Movement" category

Property Name Type Default
IdleSequence Anim Sequence Base None
  Anim Sequence to use when the character is idle.
 
MovementBlendSpace Blend Space Base None
  Blend Space used for movement with the particular weapon.
 

Next will be the Jump animations which will be created in the "Jumping" category

Property Name Type Default
JumpStartSequence Anim Sequence Base None
  Anim Sequence to use when the character starts jumping
 
JumpLoopSequence Anim Sequence Base None
  Anim Sequence to use when the character is in the air during a jump or fall.
 
JumpEndSequence Anim Sequence Base None
  Anim Sequence to use when the character has landed back on the ground
 

Next we will define our Attack Animations under the "Attacks" category. We use a single montage to define how our attacks will work even when we have a two hit combo.

This is a simple combat system but in the design of your own combat system there is nothing that is stopping you from splitting up these animations into different montages, you would simply need to add a mechanism of retrieving each montage such as a combo number to the getter function or separate functions for each montage along the lines of "GetAttackOneMontage" and "GetAttackTwoMontage" added to the interface.

Property Name Type Default
AttackMontage Anim Montage Base None
  Anim Montage to use when the character starts attacking
 

Next we will define our Guard Animations under the "Special" category. I use the special category to denote special actions a weapon may use, for instance bows may Aim instead of Guard in other systems.

Property Name Type Default
GuardMontage Anim Montage Base None
  Anim Montage to use when the character is guarding
 

Next we will define our Stun Animations under the "Stun" category. As noted when guarding an incoming attack will cause your weapon to deflect. In a more advanced example (coming soon) we'll implement a Deflect and Knockback mechanic where a power attack can break through a guard and knock back the struck character. Hense the category "Stun".

Property Name Type Default
DeflectionMontage Anim Montage Base None
  Anim Montage to use when the character's attack was deflected by a block.
 

Next we will define Combat Relax and Ready Animations under the "Combat Mode" category. These are the animations used for readying and relaxing each weapon. The system we build will play a separate animation for each equipped weapon in the hand. For instance a sword on your hip and a shield on your back will play two animations to remove them from their relaxed sockets.

Property Name Type Default
ReadyMainHandMontage Anim Montage Base None
  Anim Montage to use for the main hand when it is readied for combat.
 
RelaxMainHandMontage Anim Montage Base None
  Anim Montage to use when for the main hand when it is relaxed and holstered.
 
ReadyOffHandMontage Anim Montage Base None
  Anim Montage to use for the off hand when it is readied for combat.
 
RelaxOffHandMontage Anim Montage Base None
  Anim Montage to use when for the off hand when it is relaxed and holstered.
 

Finally we have two configuration variables which will be created in the "Config" category.  This configurations will later be used to denote the properties of a shield versus a melee weapon.

Property Name Type Default
bHasMainHandAnimations bool True
  Indicates that this animation data has animations for the main hand weapon
 
bHasOffHandAnimations bool True
  Indicates that this animation data has animations for the off hand weapon
 

Back to Top

7.3.2 Implement Combat Demo Animation Interface

Now we will implement our BPI_DemoAnimationData interface.  Note that the Order of the functions we implement may not align with the order they appear in the interface section of "My Blueprints".  I am implementing them in the same order we defined the variables that go with each function.

Implement Get Idle Sequence
Fig 7.3.2.1 Implement Get Idle Sequence

Go to "GetIdleAnimationSequence" and implement it by dragging the "Idle Sequence" Variable we created into the "Idle Sequence" Output parameter.

Implement Get Movement Blendspace
Fig 7.3.2.2 Implement Get Movement Blendspace

Go to "GetMovementBlendSpace" and implement it by dragging the "Movement Blend Space" Variable we created into the "Movement Blend Space" Output parameter.

Implement Get Jump Start Sequence
Fig 7.3.2.3 Implement Get Jump Start Sequence

Go to "GetJumpStartSequence" and implement it by dragging the "Jump Start Sequence" Variable we created into the "Jump Start Sequence" Output parameter.

Implement Get Jump Loop Sequence
Fig 7.3.2.4 Implement Get Jump Loop Sequence

Go to "GetJumpLoopSequence" and implement it by dragging the "Jump Loop Sequence" Variable we created into the "Jump Loop Sequence" Output parameter.

[IMAGE: 7.0_ImpGetJumpEndSequence]

Implement Get Jump Loop Sequence
Fig 7.3.2.5 Implement Get Jump Loop Sequence

Go to "GetJumpEndSequence" and implement it by dragging the "Jump End Sequence" Variable we created into the "Jump End Sequence" Output parameter.

Implement Get Attack Montage
Fig 7.3.2.6 Implement Get Attack Montage

Go to "GetAttackMontage" and implement it by dragging the "Attack Montage" Variable we created into the "Attack Montage" Output parameter.

Implement Get Guard Montage
Fig 7.3.2.7 Implement Get Guard Montage

Go to "GetGuardMontage" and implement it by dragging the "Guard Montage" Variable we created into the "Guard Montage" Output parameter.

Implement Get Deflection Montage
Fig 7.3.2.8 Implement Get Deflection Montage

Go to "GetDeflectionMontage" and implement it by dragging the "Deflection Montage" Variable we created into the "Deflection Montage" Output parameter.

Implement Get Ready Combat Montage
Fig 7.3.2.9 Implement Get Ready Combat Montage

Go to "GetReadyCombatMontage".  Drag from the "handType" input variable and create a switch node to split logic between getting the Main Hand or Off Hand weapon montage.  For both "Invalid" and "MainHand" we will return the "Ready Main Hand Montage" variable.  For "Off Hand" we will return "Ready Off Hand Montage".

Implement Get Relax Combat Montage
Fig 7.3.2.10 Implement Get Relax Combat Montage

Go to "GetRelaxCombatMontage".  Drag from the "handType" input variable and create a switch node to split logic between getting the Main Hand or Off Hand weapon montage.  For both "Invalid" and "MainHand" we will return the "Relax Main Hand Montage" variable.  For "Off Hand" we will return "Relax Off Hand Montage".

Implement Has Off Hand Aniamtions
Fig 7.3.2.11 Implement Has Off Hand Animations

Now open up "Has Off Hand Animations".  This function will tell our combat system if this data asset contains off hand animations that should be used for readying and relaxing weapons.

To Implement simply get "Has Off Hand Animation" and feed it into the return node.

Back to Top

7.4 Demo Animation Set

The Animation Set is a container object that is meant to be customized to your combat system specifications and hold the current "Set" of animations to be leveraged and played.  This includes Animation Sequences, Montages, Blendspaces, and anything else animation related.  The central idea of this is to blend the animations of two different weapons such as a sword and shield.  A sword may have it's own blocking animation to play for when the player does not have a shield equipped but when they do have a shield equipped it should use the shield's blocking animation instead.  How these animations are blended for the main hand and off hand is based on your own design logic and implemented within your specialized BP_DemoWeaponManager.

Open the Animaton Set Blueprint
Fig 7.4.0.1 Open the Animation Set Blueprint

First open up the BP_DemoAnimationSet blueprint we created in "DemoContent/Core/Blueprints/DataTypes".

Add Interfaces
Fig 7.4.0.2 Add Interfaces

Now select "Class Settings" and under the "Interfaces" tab in "Details" panel expand the "Interfaces" section and click the "Add" button.  Search for "BPI Demo Animation Data" and select it.  Then hit the "Add" button again and search for "BPI Demo Animation Set" interface and select it. 

The Animation Set object is updated as weapons are added and removed from the character allowing them to swap between animations quite smoothly.  This is why it leverages both "BPI_DemoAnimationData" and "BPI_DemoAnimationSet" interfaces but also why the getter functions and setter functions are on different interfaces.  The reason being that the BP_DemoWeaponAnimationData (which implements the "BPI_DemoAnimationData") is never updated by setters but the BP_DemoAnimationSet is updated and used to retrieve animations from the Animation Blueprint and the character.

Back to Top

7.4.1 Setup Animation Set Variables

Now we setup the variables we will need for the Animation Set.  These will look very similar to the variables we added to the BP_DemoAnimationData object because the Animation Set is updated according to the animations within the Animation Data object.  Depending on the make up of your game it could also be a much more concise set of animation values than the Animation Data object as it will only need to hold the animations relevant to the character currently using it.  For instance if your game has different animations based on gender and race your Animation Data may contain the animations for all the races and genders and the combinations of each while the Animation Set will contain only the animation for your character's race and gender.

I'm not going to expand as much on each of these sequences more than I already did in the previous section.  If you are skimming the tutorial and are wondering why these are defined the way they are see the previous section on setting up the BP_DemoAnimationData which uses similar variable properties that are copied to the Animation Set at runtime.

Create Variables
Fig 7.4.1.1 Create Variables

We'll start with movement animations which will be created in the "Movement" category

Property Name Type Default
IdleSequence Anim Sequence Base None
  Anim Sequence to use when the character is idle.
 
MoveBlendSpace Blend Space Base None
  Blend Space used for movement with the main hand weapon
 

Next will be the Jump animations which will be created in the "Jumping" category

Property Name Type Default
JumpStartSequence Anim Sequence Base None
  Anim Sequence to use when the character starts jumping
 
JumpLoopSequence Anim Sequence Base None
  Anim Sequence to use when the character is in the air during a jump or fall.
 
JumpEndSequence Anim Sequence Base None
  Anim Sequence to use when the character has landed back on the ground
 

Next we will define our Attack Animations under the "Attacks" category.

Property Name Type Default
AttackMontage Anim Montage Base None
  Anim Montage to use when the character starts attacking
 

Next we will define our Guard Animations under the "Special" category.

Property Name Type Default
GuardMontage Anim Montage Base None
  Anim Montage to use when the character is guarding
 

Next we will define our Stun Animations under the "Stun" category.

Property Name Type Default
DeflectionMontage Anim Montage Base None
  Anim Montage to use when the character's attack was deflected by a block.
 

Next we will define Combat Relax and Ready Animations under the "Combat Mode" category.

Property Name Type Default
ReadyMainHandMontage Anim Montage Base None
  Anim Montage to use for the main hand when it is readied for combat.
 
RelaxMainHandMontage Anim Montage Base None
  Anim Montage to use when for the main hand when it is relaxed and holstered.
 
ReadyOffHandMontage Anim Montage Base None
  Anim Montage to use for the off hand when it is readied for combat.
 
RelaxOffHandMontage Anim Montage Base None
  Anim Montage to use when for the off hand when it is relaxed and holstered.
 

Back to Top

7.4.2 Implement Demo Animation Data Interface

We will start with implementing our Getters which are in the BPI_DemoAnimationData interface.  Do note that once again the order of these functions may appear differently in the interface's section of "My Blueprints".  I am implementing them in the same order as the variables they are designed to fetch data from.

Implement Get Idle Sequence
Fig 7.4.2.1 Open the Animation Set Blueprint

Go to "GetIdleAnimationSequence" and implement it by dragging the "Idle Sequence" Variable we created into the "Idle Sequence" Output parameter.

Implement Get Movement Blend Space
Fig 7.4.2.2 Get Movement Blend Space

Go to "GetMovementBlendSpace" and implement it by dragging the "Movement Blend Space" Variable we created into the "Movement Blend Space" Output parameter.

Implement Get Jump Start Sequence
Fig 7.4.2.3 Get Jump Start Sequence

Go to "GetJumpStartSequence" and implement it by dragging the "Jump Start Sequence" Variable we created into the "Jump Start Sequence" Output parameter.

Implement Get Jump Loop Sequence
Fig 7.4.2.4 Get Jump Loop Sequence

Go to "GetJumpLoopSequence" and implement it by dragging the "Jump Loop Sequence" Variable we created into the "Jump Loop Sequence" Output parameter.

Implement Get Jump End Sequence
Fig 7.4.2.5 Get Jump End Sequence

Go to "GetJumpEndSequence" and implement it by dragging the "Jump End Sequence" Variable we created into the "Jump End Sequence" Output parameter.

Implement Get Attack Montage
Fig 7.4.2.6 Get Attack Montage

Go to "GetAttackMontage" and implement it by dragging the "Attack Montage" Variable we created into the "Attack Montage" Output parameter.

Implement Get Guard Montage
Fig 7.4.2.7 Get Guard Montage

Go to "GetGuardMontage" and implement it by dragging the "Guard Montage" Variable we created into the "Guard Montage" Output parameter.

Implement Get Deflection Montage
Fig 7.4.2.8 Get Deflection Montage

Go to "GetDeflectionMontage" and implement it by dragging the "Deflection Montage" Variable we created into the "Deflection Montage" Output parameter.

Implement Get Ready Combat Montage
Fig 7.4.2.9 Get Ready Combat Montage

Go to "GetReadyCombatMontage".  Drag from the "handType" input variable and create a switch node to split logic between getting the Main Hand or Off Hand weapon montage.  For both "Invalid" and "MainHand" we will return the "REady Main Hand Montage" variable.  For "Off Hand" we will return "Ready Off Hand Montage".

Implement Get Relax Combat Montage
Fig 7.4.2.10 Get Relax Combat Montage

Go to "GetRelaxCombatMontage".  Drag from the "handType" input variable and create a switch node to split logic between getting the Main Hand or Off Hand weapon montage.  For both "Invalid" and "MainHand" we will return the "Relax Main Hand Montage" variable.  For "Off Hand" we will return "Relax Off Hand Montage".

Back to Top

7.4.3 Implement Demo Animation Set Interface

Now we will implement the BPI_DemoAnimationSet interface.  Do note that as before the order of these functions may appear differently in the interfaces section of "My Blueprints".  I am implementing them in the same order as the variables they are designed to set and change. 

We setup the Setter functions to always return the new value being set.  This allows us to keep each function as a Function in Blueprint instead of an Event which I personally feel is just a cleaner implementation for interfaces than Events that appear on the Event Graph and cannot leverage local function variables if need be.

Implement Set Idle Sequence
Fig 7.4.3.1 Implement Set Idle Sequence

Go to "SetIdleSequence" and implement it by dragging the "Idle Sequence" Variable on to the map as a Set (you can hold alt to auto select setter).  Then drag the "In Idle Animation" input parameter to the "Idle Sequence" set node.  Finally drag the result of the "Idle Sequence" set node to the output parameter "Out Idle Sequence".

Implement Set Movement Blend Space
Fig 7.4.3.2 Implement Set Movement Blend Space

Go to "SetMovementBlendSpace" and implement it by dragging the "Movement Blend Space" Variable on to the map as a Set (you can hold alt to auto select setter).  Then drag the "In Movement Blend Space" input parameter to the "Movement Blend Space" set node.  Finally drag the result of the "Movement Blend Space" set node to the output parameter "Out Movement Blend Space".

Implement Set Jump Start Sequence
Fig 7.4.3.3 Implement Set Jump Start Sequence

Go to "SetJumpStartSequence" and implement it by dragging the "Jump Start Sequence" Variable on to the map as a Set (you can hold alt to auto select setter).  Then drag the "In Jump Start Animation" input parameter to the "Out Jump Loop Sequence" set node.  Finally drag the result of the "Jump Start Sequence" set node to the output parameter "Out Idle Sequence".

Implement Set Jump Loop Sequence
Fig 7.4.3.4 Implement Set Jump Loop Sequence

Go to "SetJumpLoopSequence" and implement it by dragging the "Jump Loop Sequence" Variable on to the map as a Set (you can hold alt to auto select setter).  Then drag the "In Jump Loop Animation" input parameter to the "Jump Loop Sequence" set node.  Finally drag the result of the "Jump Loop Sequence" set node to the output parameter "Out Jump Loop Sequence".

Implement Set Jump End Sequence
Fig 7.4.3.5 Implement Set Jump End Sequence

Go to "SetJumpEndSequence" and implement it by dragging the "Jump End Sequence" Variable on to the map as a Set (you can hold alt to auto select setter).  Then drag the "In Jump End Animation" input parameter to the "Jump End  Sequence" set node.  Finally drag the result of the "Jump End Sequence" set node to the output parameter "Out Jump End Sequence".

Implement Set Attack Montage
Fig 7.4.3.6 Implement Set Attack Montage

Go to "SetAttackMontage" and implement it by dragging the "Attack Montage" Variable on to the map as a Set (you can hold alt to auto select setter).  Then drag the "In Attack Montage" input parameter to the "Attack Montage" set node.  Finally drag the result of the "Attack Montage" set node to the output parameter "Out Attack Montage".

Implement Set Guard Montage
Fig 7.4.3.7 Implement Set Guard Montage

Go to "SetGuardMontage" and implement it by dragging the "Guard Montage" Variable on to the map as a Set (you can hold alt to auto select setter).  Then drag the "In Guard Montage" input parameter to the "Guard Montage" set node.  Finally drag the result of the "Guard Montage" set node to the output parameter "Out Guard Montage".

Implement Set Deflection Montage
Fig 7.4.3.8 Implement Set Deflection Montage

Go to "SetDeflectionMontage" and implement it by dragging the "Deflection Montage" Variable on to the map as a Set (you can hold alt to auto select setter).  Then drag the "In Deflection Montage" input parameter to the "Deflection Montage" set node.  Finally drag the result of the "Deflection Montage" set node to the output parameter "Out Deflection Montage".

Implement Set Ready Combat Montage
Fig 7.4.3.9 Implement Set Ready Combat Montage

Go to "SetReadyCombatMontage".  Drag from the "handType" input variable and create a switch node to split logic between getting the Main Hand or Off Hand weapon montage.  For both "Invalid" and "MainHand" we will set the "Ready Main Hand Montage" variable.  For "Off Hand" we will set "Ready Off Hand Montage".  Finally return the set value of "Ready Main Hand Montage" or "Ready Off Hand Montage".  You can copy and paste a new return node for the Off Hand montage.

Implement Set Relax Combat Montage
Fig 7.4.3.10 Implement Set Relax Combat Montage

Go to "SetRelaxCombatMontage".  Drag from the "handType" input variable and create a switch node to split logic between getting the Main Hand or Off Hand weapon montage.  For both "Invalid" and "MainHand" we will set the "Relax Main Hand Montage" variable.  For "Off Hand" we will set "Relax Off Hand Montage".  Finally return the set value of "Relax Main Hand Montage" or "Relax Off Hand Montage".  You can copy and paste a new return node for the Off Hand montage.

Back to Top


8.0 Setup Weapon Actor

Now we will set up our customized Weapon Actors that the combat system leverages to load and represent weapons in your game.  The weapon actors come with both a WeaponSkeletalMesh and a WeaponStaticMesh component allowing them to leverage either types of meshes for gameplay.

Open Weapon Actor Blueprint
Fig 8.0.1 Open Weapon Actor Blueprint

Open up the BP_DemoWeaponActor Bleprint

Create the Power Variable
Fig 8.0.2 Create the Power Variable

First we will define the variables we need for our weapon.  Under "My Blueprint" panel find and expand the "Variables" section. 

Press the "+" button to add a new variable. 

Name the variable "Power" and set it's type to Float. 

Compile the Blueprint and then give it a default Power value of 5.  This means that by default all weapons in our game will deal 5 points of damage.

Find the Override Button
Fig 8.0.3 Find the Override Button

Now we will override a few functions. Hover your mouse over the the "Functions" section above the "Variables" section until the "override" button appears. 

[IMAGE: 8.0_OvrOnWeaponDataLoaded]

Override On Weapon Data Loaded
Fig 8.0.4 Override On Weapon Data Loaded

Press the Override button and you should see a list of functions that can be overriden.  Search by typing "OnWeaponDataLoaded".

[IMAGE: 8.0_ImpOnWeaponDataLoaded]

Implement On Weapon Data Loaded
Fig 8.0.5 Implement On Weapon Data Loaded

This function is called when the weapon data has finished loading from disk.  Here we will use it to set our weapon properties when the data has finished.  For the most part we do not have to worry about setting the weapon visual properties or even which mesh component to use, the system handles that for you interally.  All you need to do is setup any custom properties the weapon needs to be updated with.

As you can see in the above image we use the function "GetWeaponData" which returns the currently loaded UPncsWeaponDataBase which will be our BP_DemoWeaponData blueprint.  We leverage the interface "BPI_StandardWeaponActorData" to fetch the Grip Type, Weapon Type, and Power Rating of the weapon and set them to the current values of the weapon actor.  We return true for habbit indicating that we handled the update.

Back to Top


9.0 Setup Weapon Manager

Open the Weapon Manager Blueprint
Fig 9.0.1 Open the Weapon Manager Blueprint

Now we will setup our Weapon Manager one of the most important objects in the combat system as it's job is to coordinate everything between the owning actor (your character) and the weapon actors.  We'll begin with inspecting the defaults and ensuring we are setup properly.

Inspect Sockets Details
Fig 9.0.2 Inspect Sockets Details

Click on "Class Defaults" and under the "Details" panel expand the "Sockets" section.  Notce that the Standard Weapon Manager holds several variables for the different sockets it uses.  Depending on the type of combat system you design, your skeleton, and the sockets you define these could be different for your own combat system.  I have attempted to be as comprehensive with the Standard Weapon Manager as possible but it may not be suitable for all game types.

Set the Default Classes
Fig 9.0.3 Set the Default Classes

Now find the "Classes" section in the "Details" panel and expand it.  Set the "BP_DemoWeaponActor" to the "Weapon Actor Class" property.  Then Set the "BP_DemoAnimationSet" to the "Animation Set Class" Property.  These indicate the types of Objects that the Weapon Manager needs to spawn

9.1 Utility Functions

Now we will be laying down some utility functions that our specialized combat system will leverage. 

9.1.1 Get Socket Name From Enum

Create Get Socket Name From Enum
Fig 9.1.1.1 Create Get Socket Name From Enum

In the "My Blueprint" panel go down to "Functions" and hit the "+" button.  Name your newly created function "GetSocketFromEnum".  Double click to start editing.

Add Input and Output Parameters
Fig 9.1.1.2 Add Input and Output Parameters

This funcitons's job is to take in the developer friendly Enum EDemoSocketType and spit out the corresponding socket FName socket used by Unreal to set the weapon actors to. The Input variable will be called "SocketType" and be of the type "EDemoSocketTypes" the enum we created in Blueprints.  The Output will be called "SocketName" and be of the type "Name".

Implement Get Socket Name From Enum
Fig 9.1.1.3 Implement Get Socket Name From Enum (click image for paste bin)

Paste Bin: Get Socket Name From Enum

Now we will implement this function.  You can leverage the paste bin to help with the implementation, you may need to remove and add the references to the variables and enum for it to work but it should still be easier than trying to eyeball the images.

First we split on the Socket Type input variable so we can individually handle each type of Socket we select for our weapons.  Then Sockets return the variable most applicable to the enum.

  • None: Simply returns the "None" default value for FNames
  • Main Hand: returns the "Main Hand Socket Name" variable
  • Off Hand: returns the "Off Hand Socket Name" variable
  • Main Arm: returns the "Main Arm Socket Name" variable
  • Off Arm: returns the "Off Arm Socket Name" variable
  • Back: returns the "Back Holster Socket Name" variable
  • Right Holster: return the "Right Side Holster Socket Name" variable
  • Left Holster: returns the "Left Side Holster Socket Name" variable.

Back to Top

9.1.2 Get Weapon Animation Data

Next we will create another function we will leverage in a later macro to control the execution flow when updating animations.

Create Get Weapon Animation Data Function
Fig 9.1.2.1 Create Get Weapon Animation Data Function

Create a new function and name it "GetWeaponAnimationData".

This function's job is to fetch the weapon animation data of the supplied hand type.  We are explicitly creating this function so that we can utilize the Standard Hand Type Enums or our custom Hand Type enums you may create in your own design. 

Input/Output Type Name
 Input EPncsStandardHandType HandType
Output Pncs Base Weapon Animation Data AnimationData
Output bool FoundData
 
Implement Get Weapon Animation Data
Fig 9.1.2.2 Create Get Weapon Animation Data Function

The Implementation of this function is relatively straight forward.  First we will use a sequence to return no animation data and false for the found data if we cannot fetch the desired weapon actor for what ever reason.  Then we use the input hand type to call the native function "GetWeaponActor" from the weapon manager.  If the weapon actor is valid then we fetch the weapon animation data it holds and returns it.

Back to Top

9.1.3 Create Execution Macro

Just so it is much easier to control the flow of execution within our blueprints we will setup a custom macro that the weapon manager will leverage.

Create a new Macro
Fig 9.1.3.1 Create a new Macro

Under "My Blueprint" panel find the "Macros" section and hit the "+" button.  This will create a new macro for us to use.  Name it "GetValidWeaponAnimationData".

Create Macro Inputs
Fig 9.1.3.2 Create Macro Inputs
Input/Output Type Name
Input Exec execute
Input EPncsStandardHandType HandType
Output Exec IsValid
Output Exec Invalid
Output Pncs Base Weapon Animation Data AnimationData
 

 

Implement Macro
Fig 9.1.3.3 Implement Macro

The implementation of this macro is very simple.  Use the function "GetWeaponAnimtionData" and supply it the macro's HandType input.  Then branch of if "GetWeaponAnimationData" returns true with it's "FoundData" variable.  If true then we go out the "IsValid" execution line.  If false then we go out the "Invalid" execution line. Reguardless of either we return what ever is returned from "GetWeaponAnimationData" be it null or valid.

9.2 Override Functions

Now we will be overriding a few functions from the "PncsStandardWeaponManager" base class.

Back to Top

9.2.1 Override Get Current Weapon Socket

This function is highly leveraged to fetch the correct socket to attach weapons to throughout the system.

In the "My Blueprints" Pannel hover your mouse over the "Functions" panel until the "override" button appears.  Click on it and search for "GetCurrentWeaponSocket" function and select it.

Implement Get Current Weapon Socket
Fig 9.2.1.1 Implement Get Current Weapon Socket

Paste Bin: Get Current Weapon Socket

To implement this function we use the supplied HandType parameter to get the Weapon Actor for that hand with the the native GetWeaponActor function.  Then we get the Weapon Data from the Weapon actor and call the BPI_StandardWeaponActorData interface function GetSocketType.  We supply the Hand Type as a parameter and then use the native "IsRelaxedState" function as the last parameters to the GetSocketType function.  Then with the Socket type retrieved we call "GetSocketNameFromEnum" function we created and return the FName value to the return node.

Back to Top

9.2.2 Override Update Animation Set

This function is responsible for coilating the animations of both the main hand and off hand into a single unified animation set used throughout the system.

Implement Update Animation Set
Fig 9.2.2.1 Implement Get Current Weapon Socket

Paste Bin: Update Animation Set

In the "My Blueprints" Panel hover your mouse over the "Functions" panel until the "override" button appears. Click on it to search for "UpdateWeaponAnimationData" function and select it.  Because of it's size you can copy the implementation from the Blueprint Paste Bin. However you may need to update interface nodes.

Update Animation Set Part 2
Fig 9.2.2.2 Update Animation Set Part 2

The implementation of this function begins with a sequence node with two paths. The last path leads to a return node that always returns true.  We utilize this as a short cut to finish without needing to manually use branches to explicit returns.

Right click and search for "Get Animation Set" and select it node onto the graph.  Right click on the "Get Animation Set" node and choose "Convert to Validated Git".  If the Animation Set has been created then the secution will proceed forward, if it is not valid than it will fall back to the first Sequence and return.  We only want to update the Animation Set if it is valid and if it is not valid you should make sure to set the Animation Set Class set to our BP_DemoAnimationSet blueprint.

From the Validated Get extend an execution line from IsValid and create a second Sequence.  This sequence will simply help us organize all the nodes we will need to make that will perform the updates.

Update Animation Set Part 3
Fig 9.2.2.3 Update Animation Set Part 3

From the first sequence execution line use the "GetValidWeaponAnimationData" macro we created with the "Main Hand" set as the parameter. 

Drag from the returned "Animation Data" object on the macro and and search for "Get Idle Sequence". 

Now drop another "Get Animation Set" node on the graph (we don't need this one validated since we already did it).

Drag a line out from the Animation Set node and search for "Set Idle Sequence" and select it.

Now connect the out put from "Get Idle Sequence" to the input of "Set Idle Sequence".

Congratulations you have just finished updating the Animation Set's Idle Animation sequence.

We repeat this same process for each of the peices of data we need to update. We use the Main Hand weapon as the major dictator for Idle, Movement, and Jump animations.  Using the same process as above update the following:

  1. Movement Blendspace
  2. Jump Start Sequence
  3. Jump Loop Sequence
  4. Jump End Sequence
Update Animation Set Part 4
Fig 9.2.2.4 Update Animation Set Part 4

Directly under the first "GetValidWeaponAnimationData" macro I created a copy to fetch the ready and relax anim montages for the main hand weapon as well as attacks, guards, and deflect animations.  From the second sequence drag a line from "Then 1" to the second macro.

From the returned "Animation Data" drag out and search for "Get Ready Combat Montage" from the BPI_DemoAnimationData interface.  Choose "Main Hand" as the hand type.  Then drop another "Animation Set" node and drag out a line to select "SetReadyCombatMontage" with "Main Hand" as the "Hand Type" parameter value.  Then connect the return from "Get Ready Combat Montage" to the input "In Ready Montage" of "Set Ready Combat Montage" node.

This is the general method of updating the Ready and relax montages of the animation set.  Now update the following additional properties of the Animation set using the two methods described.

  1. Relax Montage
  2. Attack Montage
  3. Guard Montage
  4. Deflection Montage
Update Animation Set Part 5
Fig 9.2.2.5 Update Animation Set Part 5

Finally we will update the Off Hand weapon montages.  Create another "GetValidWeaponAnimationData" node but with "Off Hand" selected as the "Hand Type" parameter.  Drag the third sequence line labled "Then 2" to the third macro.

From the returned "Animation Data" drag out an search for "Get Ready Combat Montage" from the "BPI_DemoAnimationData" interface.  Chose "Off Hand" as the hand type.  Then Drop another "Animation Set" node and drag outa line to select "Set Ready Combat Montage" with "Off Hand" selected in the "Hand Type" parameter.  Then connect the return from the "Get Ready Combat Montage" to the input parameter "In Ready Montage" on the "Set Ready Combat Montage" node.

Repeat this process for the Relax Combat Montage. 

And that is how you keep your Animation Sets updated through out the game play.  Every time weapons change in the manager this function is called to update all the weapons in the animation set.  Then the animation set is leveraged by the Animation Blueprint and the Character to play the specific animations needed for that weapon configuration.

Back to Top


10 Character Interface

Now things are starting to come together and converge on our Character.  One thing I like to do when developing any game with Unreal Engine is rather than rely on constantly casting my character to a specific type in blueprint I simply create an interface that external systems can use with Actor, Pawn, or Characters throughout the system.  This saves on having to perform casts within blueprints which has an added benefit of keeping the reference links to various assets fairly low.  The reason is that some blueprints can have references to other assets such as meshes, materials, and textures.  By itself UE4 does a great job of not loading these assets into memory during gameplay until they are needed.  However performing casts to specific types in blueprints to other Blueprint Types causes those additional assets referenced by the blueprint to load and in some situations you may not even need the thing you are trying to cast to because the object you are casting is not of that specific blueprint type.  This is but one reason I leverage interfaces heavily in my development.

Open Demo Character Interface
Fig 10.0.1 Open Demo Character Interface

Lets open up the BPI_DemoCharacter Interface found in "DemoContent/Core/Blueprints/Interfacers".

Demo Character Interface
Fig 10.0.2 Demo Character Interface

The first category we will define is the "BPI Demo Character | Animation" category.  Here we will define the function's we will leverage to start playing various animations for the combat system.

Function Name Input/Output Type Name
Play Attack Animation Input integer Combo Number
  Input byte Action Data
  Output bool Is Playing
  Start playing an attack animation based on the supplied combo number and additional action data parameters
 
Play End Attack Animation Input integer Combo Number
  Output bool Is Playing
  Play any Ending Animation that is needed to end an attack series.
 
Play Start Guard Animation Output bool Is Playing
  Starts playing the animation for Guarding
 
Play End Guard Animation Output bool Is Playing
  Starts playing the animation to stop Guarding
 
Play Attack Deflected Animation Output bool Is Playing
  Starts playing the deflected attack animation.
 

Now we will define our "BPI Demo Character | States" category.  This category plays a role in easily fetching the current state of our character.

Function Name Input/Output Type Name
Is Active Blocking Output bool Is Blocking
  Returns true if the character is currently blocking.
 
Is Stunned Output bool Is Stunned
  Returns true if the character is currently stunned.
 
IsRangedWeapon Output bool Is Ranged Weapon
  Returns true if the character is currently equipped with a ranged weapon.
 
  Input integer Combo Number
GetHandTypeFromComboNumber Output EPncsStandardHandType HandType
  Return the EPncsStandardHandType based on the Combo Number
 
IsPrecisionDemo Output boolean IsPrecisionDemo
  Get flag indicating that we are using the precision target collection system.
 

Now we will define our "BPI Demo Character | Stats" category. This category will hold methods to query stats, specifically health.

Function Name Input/Output Type Name
Get Health Output integer Health
  Get the current amount of health the character has.
 
Get Total Health Output integer Total Health
  Get the total amount of health the character has.
 

Back to Top


11 Setup Demo Character Base

 Finally we get to bring it all together with the BP_DemoCharacterBase.  Unfortunatly this is still only the initial setup phase of our combat system as the next two tutorials are geared toward implementing our combat system so you will not have a fully working system by the end of this.

Open Character Base
Fig 11.0.1 Open Character Base

Open up the BP_DemoCharacterBase blueprint in "DemoContent/Core/Blueprints/Character" folder. 

11.1 Interfaces and Components

Add Interfaces
Fig 11.1.1 Add Interfaces

Now select "Class Settings" and under the "Interfaces" tab in the "Details" panel expand the it and click the "Add" button.

Search for "Pncs Weapon Owner" interface and select it.

Hit the "Add" button again and search for "Pncs Unified Controller Pawn" interface and select it.

Once again hit the "Add" button and search for "BPI_DemoCharacter".

Add Weapon Manager Component
Fig 11.1.2 Add Weapon Manager Component

Now in the "Components" panel click the "Add Component" button.

Search for "BP Combat Demo Weapon Manager" and select it to add it to the components for our character.

Back to Top

11.2 Setup Variables

We'll need ot add a couple of variables to our character for tracking.

Add Variables
Fig 11.2.1 Add Variables

We'll start with our weapon references which we will create under the "Weapons" category.

Property Name Type Default Replication
Main Hand Weapon Actor BP Demo Weapon Actor None Replicated
  Reference to the weapon actor set to the main hand.
 
Off Hand Weapon Actor BP Demo Weapon Actor None Replicated
  Reference to the weapon actor set to the off hand.
 

The next set of variables will be our stats and will have the category "Stats".

Property Name Type Default Replication
Current Health integer 100 Replicated
  The current amount of health the character has.
 
Max Health integer 100 Replicated
  The total Health the character has
 
Is Dead bool false RepNotify
  flag indicating that the character is dead
 

Last we'll create a variable to help us control the ragdoll a bit, this will have the category "Config"

Property Name Type Default Replication
PelvicBoneName FName pelvis None
  Name of the pelvic bone of the character's skeleton.
 

Back to Top

11.3 Setup Custom Functions

Now we will setup some useful functions we will be leveraging for our implementation.

11.3.1 Handle Target Hit

Create Handle Target Hit
Fig 11.3.1.1 Create Handle Target Hit

In the "My Blueprint" panel find the "functions" section and click on the "+" button to create a new function.  Name it "Handle Target Hit" and give it the category "Targeting". 

Add Parameters
Fig 11.3.1.2 Add Parameters

Next we will create the following inputs and outputs:

Input/Output Type Name
Input Actor Hit Target
Output bool Is Valid Target
 

We will leave the implementation of this function empty for now. 

When we perform an attack the targeting system runs a few checks on any hit actor it comes in contact with before adding it to a list of hit actors so that we only strike an actor once per attack.  The behavior for this is left pretty open for developers to handle so you could perform attacks that strike multiple targets, only one target, or add logic to do stop the attack under certain circumstances such as guarding.   We'll be using htis function and overriding it in later tutorials to handle a small section of validation to determine if a hit target should be added to the hit list or not.

Back to Top

11.3.2 Set Ragdoll

Now we will implement a useful function for later "Set Ragdoll".  this function will cause our character to go into ragdoll when we die.  While there are a few methods to leverage ragdoll, this is by far the best method I have seen and used.

Create Set Ragdoll
Fig 11.3.2.2 Create Set Ragdoll

Once again create a new function and call it "SetRagdoll" and put it under the category of "Ragdoll".

Now create the input variable we will use to toggle rag doll on and off.

Input/Output Type Name
Input boolean Is Ragdoll
 

 

Set Ragdoll
Fig 11.3.2.1 Implement Set Ragdoll

Paste Bin: Set Ragdoll

Go to the paste bin link above to better inspect this function along with the images.  You can also copy and paste from the paste bin but keep in mind you may need to update variable references in your implementation.

As you can see the implementation runs through and turns on or off various things according to the value of the "Is Ragdoll" input variable.

Set Ragdoll Part 2
Fig 11.3.2.3 Set Ragdoll Part 2

First we grab an instance of the supplied input variable "Is Ragdoll" and use a not boolean node to enable or disable Replicated Movement for the entire actor.

Then we use a "select" statement to change the character's Movement Mode on the "Character Movement Component" to "Walking" if ragdoll is false or "None" if ragdoll is true.

Set Ragdoll Part 3
Fig 11.3.2.4 Set Ragdoll Part 3

Then still using the "Is Ragdoll" input variable we use another select statement to Enable all collision if false or set the Capsule Component to "No Collision" if true.  This will stop the character's skeleton from interacting with capsule itself.

Then we use another select with the "Is Ragdolll" variable to set the Collision Object Type of the mesh to "CharacterBody" if false and "PhysicsBody" if true.

Set Ragdoll Part 4
Fig 11.3.2.5 Set Ragdoll Part 4

Next we get our "Main Hand Weapon Actor" and "Off Hand Weapon Actor" references and check if they are valid.  If they are valid we will disable collision on them completely.  This will keep the physics of the weapon meshes themselves from colliding and causing chaos when the character is dead.

Set Ragdoll Part 5
Fig 11.3.2.6 Set Ragdoll Part 5

The final node will enable our ragdoll physics on the character mesh.  Grab the "Mesh" component of our character and drag a line and search for "Set All Bodies Below Simulate Physics".  Grab the variable we created "Pelvic Bone Name" and connect it to the "In Bone Name".  Then Drag the line from "Is Ragdoll" into the "New Simulate" input node of the function.

That's it our ragdoll function is finished.

Back to Top

11.3.3 OnRep_IsDead

Now we will implement our OnRep function for the "Is Dead" parameter we created earlier.  You will not need to "create" this function as it is immedately created upon selecting "RepNotify" for the replication setting of "Is Dead".  Double Click to edit the function.

Implement OnRep_IsDead
Fig 11.3.3.1 Implement OnRep_IsDead

We implement this function simply by calling our "Set Ragdoll" function with the current value of "Is Dead" as the input param to "Is Ragdoll".  When the value of "Is Dead" changes on the server it is replicated to our client and "OnRep_IsDead" is called. Thus when our character goes into ragdoll on the server it will go into ragdoll on the client. 

We use RepNotify for this instead a Multicast function because the replication of the "Is Dead" variable can be done reliably in large world settings while a reliable multicast function should never be used in large world in UE4 due to Net Relevancy.  That is to say the use of a reliable multicast function could be called on an Actor that may not be relevant to the player which can cause performance problems or worst a client crash.  And we do not want to risk using an Unreliable multicast because the connected client may not recieve that function and leave our defeated enemy just standing about.

11.3.4 On Character Dead

Now we will implement one of the few events our character will use "On Character Dead".  This Event will fire when the character takes enough damage to bring their health to zero.

Create On Character Dead Event
Fig 11.3.4.1 Create On Character Dead

First go to the "Event Graph" and right click on it and search for "Add Custom Event" and click on it.

Name this event "OnCharacterDead"

Drop in a node for "Set Ragdoll" and check it as "true".

Then right click and search for "Set Is Dead" and select it.

Check the "Is Dead" Value to on or true.

11.3.5 Any Damage

Add Event AnyDamage
Fig 11.3.5.1 Add Event AnyDamage

This next event we will be overriding rather than creating.  This is how we will be dealing damage, depending on your game you can use any one of the UE4 built in damage functions.  For the design of this combat system I have decided I don't really care how my character recieves damage I just want them to take the damage.

Implement Event AnyDamage
Fig 11.3.5.2 Implement Event Any Damage

Paste Bin: Event Any Damage

 Right click on the Event Graph and search for "Event AnyDamage" and select it from the list.

Implement Event AnyDamage Part 1
Fig 11.3.5.3 Implement Event Any Damage Part 1

Drag the "Current Health" node onto the graph and subtract it's value from the supplied damage.  Because "Damage" is a float value it will be automatically truncated, again the design of this system does not care about values less than 1. 

I use a clamp between the Max health and 0 to keep the final value of the current health within a desired range.

Finally I set the value of my current health to the new value.

Implement Event AnyDamage Part 2
Fig 11.3.5.4 Implement Event Any Damage Part 2

For the demo we will not get into creating a Health Bar, at least not in this current version of the demo.  The Final project will feature a working health bar but implementing that will be left up to you. Instead for testing purposes I am simply going to print the the screen or log the value of the struck character's health.  I use a Append Node to display the character that was hit, the damage it took, and the amount of health remaining.

Implement Event AnyDamage Part 3
Fig 11.3.5.5 Implement Event Any Damage Part 3

The final bit checks if the "Current Health" value is Less then or equal to 0, which is should never be less than 0 but I put that there just in case.  If it is less then or equal to zero then we call "On Character Dead".  This sets the character to ragdoll state and sets "Is Dead" to true. This then replicates to all clients and with a "RepNotify" causes the ragdoll state to trigger on all connected clients that are relevent to your character.

11.3.6 Toggle Combat Ready

Now we need a way to toggle between combat ready and relaxed.  Per the design of this combat system the character can have their weapons put away or draw them to perform attacks.   For demonstration purposes we are going to hard wire the "F" key as our ready or relax weapon button.  There are other, and better, methods of implementing input but that is beyond the scope of this tutorial.

Input Graph
Fig 11.3.6.1 Input Graph

Notice that I have created a special "InputGraph".  This is a personal choice I use for my development in order to keep my Event graphs clean.  I have seen countless Blueprints cluttered with nodes which makes navigating and fixing bugs quite a task even when they are well documented and it can get quite overwhelming.  In General I will have at most 3 graphs like this. The Event Graph is the standard we all know.  The Input Graph is where I add all Input events.  The RpcGraph is where I keep all the events that manage server,client, and multicast calls.

Add the F Keyboard Event
Fig 11.3.6.2 Add the F Keyboard Event

To implement our Toggle Combat right click on the graph and look for "F keyboard".  Often times finding specific keys can be tricky, I find adding the "keyboard" part helps but you'll still need to scroll around to find the exact one you want.

Implement the Toggle Ready Function
Fig 11.3.6.3 Implement the Toggle Ready Function

Then we drag and drop our BP_CombatDemoWeaponManager component onto the graph as a get.

Then We will draw a line from the Weapon Manager Component and search for "Set Is Combat Mode Enabled".

Then we will draw a second line from the Weapon Manager and look for "Is Combat Mode Enabled".

From the return of "Is Combat Mode Enabled" we will draw a line and look for "Not Boolean".

Now we take the value of the "Not" and connect it to the "Is Enabled"

And that is how we will toggle between Weapon Ready and Relaxed.

11.4 Implement Unified Controller Pawn Interface

Now we will implement the IPncsUnifiedControllerPawn interface. The main goal of this interface is a sort of integration interface to allow the PNCS to easily integrate into any additional systems you may leverage.  It is implemented on both your Actor/Pawn/Character and the Controller.  For external systems that take Actors as parameters you can use this interface to fetch the controleld Pawn or the Controller if needed without using hard casting to do so.

Implement Get Pawn (PNCS)
Fig 11.4.1 Implement Get Pawn (PNCS)

Click on the "Get Pawn (PNCS)" interface function.  To implement it we simply right click and search for "self" and select "Get a reference to self".  Then connect "self" to the output parameter.  This function is useful for systems that accept Actor as a parameter but you may not be entirely sure if that Actor is a Character or Controller.  Calling this function ensures you have the pawn/character.

Implement Get Controller (PNCS)
Fig 11.4.1 Implement Get Controller (PNCS)

Now go to "Get Controller (PNCS)" function.   To implement this function right click and search for "Get Controller".  Take the output of the "Get Controller" function and feed it into the output.

Implement Is Controlled Player (PNCS)
Fig 11.4.1 Implement Is Controlled Player (PNCS)

Now go to "Is Controlled Player (PNCS)" function.  We implement this function by first getting the Controller and checking if it is valid.  If the controller is valid we then use the same "Is Controlled Player (PNCS)" function that is implemented on our controller and return it's value.

This function comes most in use for making decisions in multiplayer games in how we transmit data between the clients and servers.  Firstly this function will always return true for player controllers on the server but only return true for a connected client's own character since connected clients only have references to their own player controllers.  Second if the controller is an AI controller this will always return false.  The system leverages this function to easily decide if certain data can or should be sent between clients and servers.

Back to Top

11.5 Implement Weapon Owner Interface

The IPncsWeaponOwner interface is the main facilitator of communication between the Weapon Manager and the Pawn and Weapon Actors.  By far this will be one of the largest interfaces we implement. As a quick note the order we implement these functions may not be the same order they appear in the list.

11.5.1 General Functions

We will begin by implementing the uncategorized functions under the "IPncs Weapon Owner" category, the ones outside "Animation", "Targets", and "Trace". These are the most numerous and will take care of the bulk of our interface.

Expand IPncs Weapon Owner Category
Fig 11.5.1.0.1 IPncs Weapon Owner Category

On the "My Blueprint" panel find the "Interfaces" section and expand the "IPncs Weapon Owner".

11.5.1.1 Get Weapon Manager

Implement Get Weapon Manager
Fig 11.5.1.1.1 Implement Get Weapon Manager

First double click on the function "Get Weapon Manager" and open the definition.  We leverage this function to easily fetch the Weapon Manager when the input parameters of other functions (such as damage) only hold Actors.  This allows us to fetch the Weapon Manager with out a cast to do so.

11.5.1.2 Set Weapon Actor

Implement Weapon Actor
Fig 11.5.1.2.1 Implement Set Weapon Actor

Paste Bin: Set Weapon Actor

First double click on "Set Weapon Actor" to open the function definition. This function is called by the Weapon Manager anytime a new Weapon Actor is created so that the owning Actor/Pawn/Character can be updated. We will be using it to add references to our weapon actors through the Character Base object.

This is the one area where I break all my previous rules and perform a hard cast to "BP_DemoWeaponActor" instead of leveraging interfaces since the only property I really need from the weapon is it's power rating.  While normally I would prefer to use an interface I also know that this is the only place I will be doing this.  The other thing is I know for sure that all weapon actors will be of the BP_DemoWeaponActor and that blueprint does not have any refernces to active assets other than the default weapon data we will give it which will need to be loaded anyway.

Implement Set Weapon Actor Part 1
Fig 11.5.1.2.2 Implement Set Weapon Actor Part 1

So the first step to implementing this function is to use a sequence that returns the WeaponActor that was sent in via input parameters.

Implement Set Weapon Actor Part 2
Fig 11.5.1.2.3 Implement Set Weapon Actor Part 2

Then out of the first sequence execution line "Then 0" we perform a cast to "BP_DemoWeaponActor" and set a local function variable simply called "Local Weapon".  You can drag the output of the cast out and select "Promote to Local Variable".

Then by right clicking and searching for "Get Hand Type" drop a node for the for the local input parameter "Hand Type" into the graph.  Drag off the node and search for "Hand Type" and select "Byte to enum EPncsStandardHandType".  Then from the conversion node drag a line off and search for "Select" and choose "Select on EPncsStandardHandType".

Implement Set Weapon Actor Part 3
Fig 11.5.1.2.4 Implement Set Weapon Actor Part 3

Place down a Set Node for the "Main Hand Weapon Actor" and the "Off Hand Weapon Actor.  Connect the select execution line for "Main Hand" to the "Main Hand Weapon Actor" set node.  Connect the select execution line for "Off Hand" to the "Off Hand Weapon Actor" set node.

Drop a get node for the "Local Weapon" variable we created and connect it to both "Main Hand Weapon Actor" and "Off Hand Weapon Actor" set nodes.

Finally Add a Return node and return "Local Weapon" variable to complete the function.

11.5.1.3 Set Weapon

Implement Set Weapon
Fig 11.5.1.3 Implement Set Weapon

The purpose of this function is to set the weapon you want the weapon actors to represent.  They will then load the data and update the weapon's apperance.

To implement this function we get the "BP_CombatDemoWeaponManager" component and drag a line off to find "Set Weapon Id" function.

Then grab the "Hand Type" input variable and connect it to the "Set Weapon Id" function's "Hand Type" input parameter.

Grab the "Weapon ID" input variable and connect it to the "Set Weapon Id" function's "Weapon Id" input parameter.

Finally Return the "Weapon ID" value.

11.5.1.4 Remove Weapon

Implement Remove Weapon
Fig 11.5.1.4 Implement Remove Weapon

Now select "Remove Weapon" and open it. This function is used to clear the currently set weapon info from the weapon actor in the specified hand.

To implement this function we grab the "BP Combat Demo Weapon Actor" component and drag a line to get the "Remove Weapon" function.

Then we connect the "Hand Type" input variable to the "Hand Type" input variable of the component's "Remove Weapon" function.

Then return the boolean value from the component's function to the interface function.

11.5.1.5 Get Weapon Owner Mesh

Implement Get Weapon Owner Mesh
Fig 11.5.1.5 Get Weapon Owner Mesh

Open up "Get Weapon Owner Mesh" function.  This function is used by the weapon manager to get the mesh object to attach the weapons to.

To implement this function we simply grab the "Mesh" component of our character and return it.

11.5.1.6 Get Weapon Owner Anim Instance

Implement Get Weapon Owner Anim Instance
Fig 11.5.1.6 Get Weapon Owner Anim Instance

Now open "Get Weapon Owner Anim Instance" function.  Internally this function is not utilized but is very useful when you need to coordinate actions between weapons and character.

To implement this function grab the "Mesh" component.

Then Pull a line out and search for "Get Anim Instance" and select it.

Return the value of "Get Anim Instance" node.

11.5.1.7 Update Single Weapon Attachment

Implement Update Single Weapon Attachment
Fig 11.5.1.7 Update Single Weapon Attachment

Select and open the function "Update Single Weapon Attachment".  This function is leveraged by the combat system for two purposes.  The first is when one of the weapons has finished loading it's data.  The second is during the ready / relax phase when you want to play ready / relax animations for each weapon.  For instance if you have a sword and shield you want to play a "ready" animation for.  When the ready animation hits the specific point, using one of the built in Anim Notifies, you can trigger it to change attachment points so that it looks like your character grabbed the weapon from it's holster.

To implement this function we grab the "BP Combat Demo Weapon Manager" and drag a line out to look for "Update Weapon Attachment".

Then we grab the "Weapon Hand" input parameter and feed it into the "Hand Type" input parameter on "Update Weapon Attachment".

Finally we simply return true.

11.5.1.8 Update All Weapon Attachments

Implement Update All Weapon Attachments
Fig 11.5.1.8 Update All Weapon Attachments

Select and open the function "Update All Weapon Attachments".  This function is used by the combat system similar to "Update Single Weapon Attachment".  for instance if you have a ready weapon animation that readies all weapons at the same time (such as dual daggers, swords, or unarmed hands).

To implement this function grab the "BP Combat Demo Weapon Manager" and drag a line out to look for the "Update Weapon Attachments".  Notice the name of one is plural "Attachments" and not "Attachment" like "Update Single Weapon Attachment" was.

Connect the execution lines and return true.

11.5.1.9 Get Weapon Actor

Implement Get Weapon Actor
Fig 11.5.1.9 Get Weapon Actor

Open up the function "GetWeaponActor".  This function allows us to fetch a weapon actor by "hand Type".

To implement this function drop in the "BP Combat Demo Weapon Manager" component node and draw a line out to look for the function "Get Weapon Actor". 

Connect the input parameter "Hand Type" to the "Hand Type" parameter on the weapon manager's "Get Weapon Actor" function.

Finally return the output parameter from the weapon manager's "Get Weapon Actor".

11.5.1.10 Get Current Weapon Socket

Implement Get Current Weapon Socket
Fig 11.5.1.10 Get Current Weapon Socket

Open up the "Get Current Weapon Socket" function.  This function is highly leveraged throughout the combat system to fetch the correct socket to attach weapons to.  You may remember we implemented a similar function on the Weapon Manager, this is the function we will be calling to implement this interface function.

To implemen this function grab the "BP Combat Demo Weapon Manager" component and drag a line out to search for "Get Current Weapon Socket".

Feed in the "Hand Type" input parameter from the interface function into the "Hand Type" input parameter of the Weapon Manager function.

Return the result of the Weapon Manager's function for the interface function.

11.5.1.11 Get Ignored Support Actors

Implement Get Ignored Support Actors
Fig 11.5.1.11 Get Ignored Support Actors

Open up the "Get Ignored Support Actors (PNCS)" interface function.  This function is highly leveraged by the Weapon Manager's trace systems for collecting targets so that it knows specifically what actors on our character to ignore damage for.

We implement this function by draging out from the output parameter and choosing "Make Array".

Click the "Add pin" button on the "Make Array" node to have 3 inputs.

Right Click and search for "self" and choose "Get a reference to self" option and connect it to the first pin in the "Make Array" node.

Then Grab both the "Main Hand Weapon Actor" and "Off Hand Weapon Actor" and connect those to pins "[1]" and "[2]".

Now when you leverage any of the Weapon Manager's target gathering methods these three actors will be exempt from it's collection data.

11.5.1.12 On Single Weapon Updated

Implement On Single Weapon Updated
Fig 11.5.1.12 On Single Weapon Updated

 Open up "On Single Weapon Updated".  This function is called when ever the data of a given weapon actor is updated and loaded.

To implement this function grab the "BP Combat Demo Weapon Manager" and drag a line out to search for "On Weapon Updated".

Connect the execution lines and return true.

11.5.1.13 Set Ammo Type

Implement Set Ammo Type
Fig 11.5.1.13 Set Ammo Type

Select and open the "Set Ammo Type" function.  This function works similar to "Set Weapon" interface function in that you specify what type of ammo your current weapon should be using.  Think of it like setting a type of arrow to a bow or a specific type of bullet to a gun.

To implement this function we get the "BP Combat Demo Weapon Manager" component and drag a lint off to find the function "Set Ammo Id".

Then we grab the supplied "Hand Type" parameter and connect it to the "Hand Type" input parameter of the weapon manager's function node.

Then Grab the supplied "Ammo Id" parameter and connect it to the "Ammo ID" input parameter of the "Set Ammo ID" function.

finally return the value of "Ammo ID" parameter.

Notice how this function allows you to specify a hand type.  Internally the weapon manager will look for the weapon actor in the given hand and set the new ammo for it to use which triggers the weapon actor to load the ammo data.  While the system we are currently building does not support dual ranged weapons there is nothing stopping you from designing a system where you have dual ranged weapons using different ammo types.

11.5.1.14 Remove Ammo

Implement Remove Ammo
Fig 11.5.1.14 Implement Remove Ammo

Now select "Remove Ammo" to open its editor.  This function is used to clear any currently set ammo from a specific weapon.

To implement this function grab the "BP Combat Demo Weapon Manager" component and drag a line off to get the "Remove Ammo" function.

Supply the "Hand Type" input parameter from the interface function and connect it to the "Hand Type" input parameter to the "Remove Ammo" function.

Connect the return from "Remove Ammo" node to the return node of the interface function.

11.5.1.15 Consume Ammo

Implement Consume Ammo
Fig 11.5.1.15 Implement Consume Ammo

Go to the "Consume Ammo" function.  We will not be implementing this function just yet and will leave it empty for now.  The idea of this function is that it is called somewhere in your system when you need to Consume ammo for a ranged weapon.  For now we will leave it as it is but later when we implement the "Projectile Demo" we will override this funciton.

11.5.1.16 Can Weapon Use Ammo

Implement Can Weapon Use Ammo
Fig 11.5.1.16 Implement Can Weapon Use Ammo

Go to "Can Weapon Use Ammo" function.  Again we will not be implementing this function just yet and will leave it as is for now.  The idea behind this function is to check if the weapon in the given hand can use the specified "Ammo ID".  The logic for this is completely implementation dependent.  You can leverage any type of system for this you want, a custom data table, data asset, configuration of the weapon itself, etc there are many many ways to implement this in your game.

11.5.1.17 On Weapon Ammo Updated

Implement On Weapon Ammo Updated
Fig 11.5.1.17 Implement On Weapon Ammo Update

Go to "On Weapon Ammo Updated" function.  This is another function we will be leaving the implementtion to a later tutorial "Projectile Demo".  The combat system knows how to update weapon actors and change their apperances as it is part of the combat system's design.  However, how you handle ranged weapon assets is completely dependent upon the design of your game.  Some designs may require something like a quiver, ammo pouch, or magazine clip to appear on the character's body.  This is what this function is for, to allow you to update the visual apperances of equipped ammo to the character or weapon's body.  Some designs may not require any visual updates and that is perfectly okay, you can ignore this function.

11.5.1.18 On Weapon Ammo Removed

Implement On Weapon Ammo Removed
Fig 11.5.1.18 Implement On Weapon Ammo Removed

Go to the "On Weapon Ammo Removed" function.  Again this is another function we will be leaving unimplemented for now until we hit the "Projectile Demo" tutorial.  For the same reasons as the "On Weapon Ammo Updated" function, this allows you to alter the apperance of any additional visual representations for a weapon's ammo.  Some combat systems may require a quiver, ammo pouch, or gun magazine to be visible while others do not.

Back to Top

11.5.2 Trace Functions

Next we will work on the set of functions geared toward target gathering. The Weapon Manager provides several easy to use trace functions that gather targets using Unreal Engine 4's trace functionalities but also santaizes and validates each struck target.

Options for these functions include an enum called EPncsTraceType which uses 3 values.  "Channel" means the trace executes using a specific trace channel such as "Camera" or "Visibility" but can also include any of the other collision object like Pawn or CharacterMesh.  "Profile" returns an FName of the collision preset you want to use such as "BLockAllDynamic" or "OverlapAll".  "Object" is one of the most powerful traces and looks for an array of various "Collision Objects" such as Pawn, Physics body, World Static, and World Dynamic".

Trace Type Example
Fig 11.5.2 Trace Type Example

It is beyond the scope of this tutorial series to teach you about UE4's Collision System and it can take a bit of time to fully understand.  If you would like to read more follow this link: UE4 Collision Documentation

11.5.2.1 Get Trace Profile

Get Trace Profile
Fig 11.5.2.1 Get Trace Profile

Expand the "Trace" sub category and open up the "Get Trace Profile" function. This funciton is used by the Targeting system when using "Profile" based traces.

We are simply going to implement this by returning "BlockAll".  To be honest this is one of my least used target gathering types but the combat system provides it in case someone finds a use for it.

Notice the Trace ID input parameter to this function.  Even though we have not used it, it is a pretty useful parameter.  Any of the built in traces can use as a parameter a "Trace Id" which is also passed to this interface function.  This allows you to decide, depending on the trace id, what profile you want to use.  You should try to keep the number of trace id's to a minimum and if you cannot develop a method of unifying all the trace id's in your game so someone does not pass along the wrong id.

11.5.2.2 Get Trace Collision Objects

Get Trace Collision Objects
Fig 11.5.2.2 Get Trace Collision Objects

Now open up "Get Trace Collision Objects". This is by far my most used trace type. This function is used by the Targeting system when using "Collision Object" type traces.  I utilize this trace most becasue it is the only trace type capable of actually returning multiple hit targets with a single trace call.  All the others will immedately stop upon hitting the first actor.

To implement this function we will drag out a line from the "Out Collison Objects" output parameter and choose "Make Array". 

In the first input simply choose "Character Body" as the collision object.

In our game we specifically are looking for other characters and so we are not going to pay attention to any sort of collision object types. That is why we are only returning "Character Body" as the collision object.  In your own games you can specify more objects including any custom built objects you have setup in the Collision Settings of your project.

Again notice the Trace ID input parameter to this function.  Even though we have not used it, it is a pretty useful parameter.  Any of the built in target gathering methods from the Weapon Manager can add a parameter called "Trace Id" which is also passed to this interface function.  This allows you to decide, depending on the trace id, what set of Collision Objects you want to use.  You should try to keep the number of trace id's to a minimum and if you cannot, I suggest developing a method of unifying all the trace id's in your game so someone does not pass along the wrong id for an attack.

11.5.2.3 Get Trace Channel

Get Trace Channel
Fig 11.5.2.3 Get Trace Channel

Finally open up "Get Trace Channel".  This is probably the second most used method of gathering targets.  However like the "profile" option it is limited to stopping immedately upon hitting one actor.  I do perfer this over profile however as their is less chance breaking it because of the "FName" output.

To implement this function we will simply select "Visibility" from the drop down list of the output parameter.

Again notice the Trace ID input parameter to this function.  Even though we have not used it, it is a pretty useful parameter.  Any of the built in target gathering methods from the Weapon Manager can add a parameter called "Trace Id" which is also passed to this interface function.  This allows you to decide, depending on the trace id, what Channel you want to use.  You should try to keep the number of trace id's to a minimum and if you cannot, I suggest developing a method of unifying all the trace id's in your game so someone does not pass along the wrong id for an attack.

Back to Top

11.5.3 Targets Functions

Once the target gathering traces have completed they send the targets over to be processed.  This category of functions allows you determine what to do when a target is struck as well as how to apply damage to them.  In general when you perform an attack you will play an animation and during the time that animation is playing you will be gathering targets using traces to determine what is hit by that attack animation.  This is what I mean when I talk about "target gathering".  We collect Targets by performing one or more traces, depending on the combat system you are building.  This could be one or more simple box, sphere, or line trace directly infront of the character.  It could also be a high precision trace executed to follow the animation of the weapon itself.  You may catch me use "trace" and "target gathering method" interchangably here because a trace is a "target gathering method".

11.5.3.1 On Target Hit

Implement On Target Hit
Fig 11.5.3.1.1 Implement On Target Hit

Paste Bin: On Target Hit

This first function is called when one of Weapon Manager trace functions (target gathering functions) hits a target.  Here we can decide what to do with this hit target.  If we find it an acceptable target we can add it to the list of hit targets kept on the Weapon Manager.  If it is not a valid target for any reason we can ignore it or even stop all future processing of targets.

First thing we will do is use a sequence with two execution lines.  The second line will go immedately to a return node that returns false.  This is an easy way to setup a failed condition without having to get too crazy with blueprint execution lines for each possible place you would need to have a fail contiion such as a cast or a banch.

From the first execution line of our sequence we will use a "Switch Has Authority" macro which is part of UE4's standard macros.  We only want to execute any damage logic if we are dealing with the authority.

Implement On Target Hit Part 1
Fig 11.5.3.1.2 Implement On Target Hit Part 1

If we are the authority then we will be using our "Handle Target Hit" function we created earlier.  In later demos we will subclass the Characer Base blueprint and override this function to handle validating a hit actor.  For now simply supply the "Hit Actor" input parameter for the interface to the "Hit Actor" to the input parameter of the "Handle Target Hit" function.

Then we create a branch from the output parameter of "Handle Target Hit".  If we have determined that the supplied hit actor to this function is not valid (for instance it may be guarding), then we do not add it to the hit Target list.

Now get the "BP Combat Demo Weapon Manager" component and draw a line from it to search for the "Add Hit Target" function.  You will want to supply both the "Hit Actor", "Hit Result", and "Trace Id" paramters to this function and ignore "Hand Type" and "Overwrite Existing Target".  Then return true

We Ignore the "Hand Type" for the "Add Hit Target" parameter because the General Target gathering functions do not supply a hand type.  Instead a Trace ID is associated with them.

11.5.3.2 On Target Precision Hit

Implement On Target Precision
Fig 11.5.3.2.2 Implement On Target Precision Hit

Paste Bin: On Target Precision Hit

This function is basically a copy of "OnTargetHit" and you can freely copy the body of "OnTargetHit" to this function and implement it. 

This function is called when a potential target actor is struck by a precision trace executed by the weapon actors.  One of the biggest differences between this function and "OnTargetHit" is the "Hand Type" parameter allowing you to fetch data from the weapon that struck the actor.  Just like "OnTargetHit" you can decide what to do with the hit target.  If we find it an acceptable target we can add it to the list of hit targets kept on the Weapon Manager.  If it is not a valid target for any reason we can ignore it or even stop the precision hits entirely.

First thing we will do is use a sequence with two execution lines.  The second line will go immedately to a return node that returns false.  This is an easy way to setup a failed condition without having to get too crazy with blueprint execution lines for each possible place you would need to have a fail contiion such as a cast or a banch.

From the first execution line of our sequence we will use a "Switch Has Authority" macro which is part of UE4's standard macros.  We only want to execute any damage logic if we are dealing with the authority.

Implement On Hit Target Part 1
Fig 11.5.3.2.2 Implement On Hit Target Part 1

If we are the authority then we will be using our "Handle Target Hit" function we created earlier.  In later demos we will subclass the Characer Base blueprint and override this function to handle validating a hit actor.  For now simply supply the "Hit Actor" input parameter for the interface to the "Hit Actor" to the input parameter of the "Handle Target Hit" function.

Then we create a branch from the output parameter of "Handle Target Hit".  If we have determined that the supplied hit actor to this function is not valid (for instance it may be guarding), then we do not add it to the hit Target list.

Implement On Hit Target Part 2
Fig 11.5.3.2.3 Implement On Hit Target Part 2

Now get the "BP Combat Demo Weapon Manager" component and draw a line from it to search for the "Add Hit Target" function.  You will want to supply both the "Hit Actor" and "Hit Result" paramters to this function and ignore Overwrite Existing Target".  Then return true

11.5.3.3 Process Hit Actor

Implement Process Hit Actor
Fig 11.5.3.3.1 Implement Process Hit Actor

Paste Bin: Process Hit Actor

Open up the "Process Hit Actor" function.  This function is called generally at the end of target gathering for each valid target collected and stored in the Weapon Manager.

Implement Process Hit Actor Part 1
Fig 11.5.3.3.2 Process Hit Actor Part 1

To implement this function we break the struct parameter sent in which is of type FPncsTargetData, a custom struct that stores hit data for the combat system.  Breaking that structure we have the properties which include the "Hit Actor", "Hit Result", "Hand Type" that hit it, and "Trace Id" that was used.

Implement Process Hit Actor Part 2
Fig 11.5.3.3.3 Process Hit Actor Part 2

Right click and search for "Apply Point Damage" node.  From the broken "PncsTargetData" struct grab a line from "hit Actor" and feed it into "Damaged Actor" parameter of "Apply Point Damage".

Because the design of this combat system dicates that the main hand weapon is always the one that deals damage we will simply grab the reference to "Main Hand Weapon Actor" as a get node.  Then we will draw out a line from the node and look for "get power" to get it's power rating.  Then draw a line from the "power" node and connect it to the "Base Damage" input of "Apply Point Damage".

From the broken "Pncs Target Data" struct grab the "Hit Result" property and feed it into the "Hit info" input parameter of "Apply Point Damage".

Then again from the "Hit Result" property split off to break the "Hit Result' struct.  Look for a property called "Impact Normal" and pull a line off of it.  Then look for the multiply "vector * float" node.  We will multiply the Impact Normal by a -1 to get the inverted direction of the impact and feed that into "Hit From direction" parameter.

Then right click and search for "Get Controller" node.  Feed the "Get Controller" node return value into the "Event Instigator" input parameter.

Now draw another line from the "Main Hand Weapon Actor" and connect it to the "Damage Causer" input node.  You can also do what I did in the pictur which was grab another refernce of the "Main Hand Weapon Actor" but it really does not matter how you do it.

Finally change the "Damage Type Class" to anything, does not matter.  I chose the generic "Damage Type".  As you define your own damage types you can change this to what ever you prefer even grabing the damage from the weapon data.

Implement Process Hit Actor Part 3
Fig 11.5.3.3.4 Process Hit Actor Part 3

Finally feed the float return value of Apply Point Damage into the return.

Back to Top

11.5.4 Animation Functions

This final section manages animations for readying and relaxing the character's weapons.  These are completely optional to implement if your combat system does not have ready or relax animation needs.  The design of our weapon system will allow us to play a ready animation for each weapon the character has equipped. 

The animation interface functions are flexible and you have a bit of space to play with them depending on your combat system design.  To show the full flexibility we will be implementing the more complicated configuration for multiple weapon ready and relax animations for each weapon.  In the easier method you only need to implement the "Start" and "On Finished" functons.

11.5.4.1 Start Ready Weapon Animation

Implement Start Ready Animation
Fig 11.5.4.1 Implement Start Ready Animation

Click and open the "Start Ready Weapon Animation".  We use this function to start playing the weapon ready animations, the native C++ of the Weapon Manager calls this function first to start the ready sequence. We then use "Play Ready Weapon Animation" which does the heavy lifting for finding the correct animation to play based on the weapon hand we start off with.

The design of our combat system will play a specialized animation for each weapon when performing a ready action.  This means that if you have a sword and shield equipped it will first pull the sword and then pull the shield.  So combat system leverages this function as the starting point for playing a sequence of animations and we well it which animation to play first.

To implement this function we will get a litteral "EPncsStandardHandType" enum node.  Then you can right click an search for "Play Ready Weapon Animation" or drag it from the interface onto the graph. 

Then connect the literal enum value to the "Hand Type" input.

Finally return the result of "Play Ready Weapon Animation".

11.5.4.2 Play Ready Weapon Animation

Implement Play Ready Weapon Animation
Fig 11.5.4.2.1 Implement Play Ready Weapon Animation

Paste Bin: Play Ready Weapon Animation

Click on and open "Play Ready Weapon Animation".  We use this function to actually execute the play animation logic. 

The design of our combat system for this tutorial will play a ready animation for each equipped weapon, meaning if you have a sword and a shield equipped you will first pull the sword an then pull the shield.  If you want to design a simpler combat system where you just play one animation to pull all your weapons you can take the implementation of this function and copy it into the "Start Ready Weapon Animation" instead.  You'll have to work out the "hand Type" variable yourself but that's part of your overall design decisions.

Implement Play Ready Weapon Animation Part 1
Fig 11.5.4.2.2 Implement Play Ready Weapon Animation Part 1

We will start implementation with a sequence node with two execution tracks.  The "Then 1" track we will attach our return node to with "false" checked.  We use the sequence node as a fall back in case any condition pops up on the main line of execution that would cause our animations to not play.

Implement Play Ready Weapon Animation Part 2
Fig 11.5.4.2.3 Implement Play Ready Weapon Animation Part 2

Now we will grab our "BP Combat Demo Weapon Manager" and pull a line to fetch the "Get Animation Set" function which returns our current "Animation Set" object. 

As any good programmer should, we validate the animation set first before trying to use it.  If this object is invalid then the execution will fall back to our sequence node that returns false.

Then we draw a line out from the "Get Animation Set" function and call the "Get Ready Combat Montage" interface function.  You can draw a line from the "Hand Type" variable or right click and search for "Get Hand Type" and connect it to the "Hand Type" input parameter of the "Get Ready Combat Montage" node.  Finally connect the "Is Valid" execution path to the "Get Ready Combat Montage" node.

Implement Play Ready Weapon Animation Part 3
Fig 11.5.4.2.4 Implement Play Ready Weapon Animation Part 3

Once again we validate the output of the "Get Ready Combat Montage" node.  If it is a valid asset execution will continue, other wise it will fall back to the "Sequence" node we created at the start and return false that no animation was played.

Now right click and search for "Play Anim Montage" and select it.  Feed the output of "Get Ready Combat Montage" node into the "Anim Montage"

Finally copy and paste or create a new return node and return true with it. 

11.5.4.3 Play Next Weapon Ready Animation

Implement Play Next Ready Animation
Fig 11.5.4.3.1 Implement Play Next Ready Animation

Paste Bin: Play Next Ready Weapon Animation

Click on and open the "Play Next Weapon Ready Animation".  This function is called by our Anim Notifies to play the next weapon ready animation.  It supplies the last weapon hand that was played so we can decide what hand to play next.  If we have played each hand then we can end the ready animation chain.

Implement Play Next Ready Animation Part 1
Fig 11.5.4.3.2 Implement Play Next Ready Animation Part 1

As usual we will use a sequence node with two lines of execution.  Should a condition along the main execution line fail we will fall back to the "Then 1" execution and end the animation chain.

Grab a reference to the "BP Combat Demo Weapon Manager" and draw a line out to search for the functon "On Finished Readying Weapon".

Right click and search for "get Last Hand Type" to drop a new reference to the supplied "Hand Type" input or simply draw a line between it and the "Hand Type' input parameter of "On Finished Readying Weapon". 

Check true the parameter "Trigger Is Ready".

Finally connect the "On Finished Readying Weapon" execution line to a Return node with the "Return Value" checked true.

Implement Play Next Ready Animation Part 2
Fig 11.5.4.3.3 Implement Play Next Ready Animation Part 2

From the Sequence "Then 0" execution line create a Branch.

Then using the "Last Hand Type" input parameter we will need to do a convert to "EPncsStandardHandType".  Draw a line from "Last Hand Type" and search for "EPncsStandardHandType" and select "Byte to enum EPncsStandardHandType".  Then draw a line from the cast and search for "==" node.  Use the drop down to select the value "Main Hand".  If "Last Hand Type" does not equal the "Main Hand" then the "Off Hand" just finished and those are our only two hands for this system so we can end the ready animations sequence.

Implement Play Next Ready Animation Part 3
Fig 11.5.4.3.4 Implement Play Next Ready Animation Part 3

After the Branch place a second branch.  We'll use this to check if the off hand weapon has a weapon set. 

Drop in a "BP Combat Demo Weapon Manager" node and draw a line from it to look for "Is Weapon Set".  This function checks if the given weapon has any sort of weapon data.

Right click on the graph and search for "EPncsStandardHandType" and choose "Literal enum EPncsStandardHandType" from the list.  Set the value to "Off Hand" and feed it into the "Hand Type" input parameter of the "Is Weapon Set" node.

Connect the return value of the "Is Weapon Set" node to the input "Condition" of the branch.

Implement Play Next Ready Animation Part 4
Fig 11.5.4.3.5 Implement Play Next Ready Animation Part 4

Now right click and search for "Play Ready Weapon Animation" and select it or drag it in from the list of interface functions.  Use the Enum Literal we created earlier and drag a line from it into the "Hand Type" of the "Play Ready Weapon Animation".  This will trigger our off hand weapon to play it's ready animation.

Now put down the last Branch.  This branch will check if the return value of "Play Ready Weapon Animation" was true.  If it is false something happened in that function where we could not play the desired animation for the hand (usually a missing animation from the animation set or the Animation Data that populates the set).  So as a final fall back we will use this branch.  In my design I have opted to simply allow it to fall back to "On Finished Readying Weapons" but you may print out a string for errors or trigger the next weapon animation (if you have more than two hands).

Finally connect the "True" execution line of the branch to a return node with "Return value" checked on to true.

11.5.4.4 Start Relax Weapon Animation

Implement Start Relax Weapon Animation
Fig 11.5.4.4 Start Relax Weapon Animation

Click and open the "Start Relax Weapon Animation".  We use this function to start playing the weapon ready animations, the native C++ of the Weapon Manager calls this function first to start the ready sequence. We then use "Play Relax Weapon Animation" which does the heavy lifting for finding the correct animation to play based on the weapon hand we start off with.

The design of our combat system will play a specialized animation for each weapon when performing a ready action.  This means that if you have a sword and shield equipped it will first pull the sword and then pull the shield.  So combat system leverages this function as the starting point for playing a sequence of animations and we well it which animation to play first.

To implement this function we will get a litteral "EPncsStandardHandType" enum node.  Then you can right click an search for "Play Ready Weapon Animation" or drag it from the interface onto the graph. 

Then connect the literal enum value to the "Hand Type" input.

Finally return the result of "Play Ready Weapon Animation".

11.5.4.5 Play Relax Weapon Animation

Implement Play Relax Weapon Animation
Fig 11.5.4.5.1 Play Relax Weapon Animation

Paste Bin: Play Relax Weapon Animation

Click on and open "Play Relax Weapon Animation".  We use this function to actually execute the play animation logic. 

The design of our combat system for this tutorial will play a relax animation for each equipped weapon, meaning if you have a sword and a shield equipped you will first put away the the sword an then put away the shield.  If you want to design a simpler combat system where you just play one animation to put away all your weapons you can take the implementation of this function and copy it into the "Start Relax Weapon Animation" instead.  You'll have to work out how the "hand Type" will or will not play into the functionality but that is part of your overall design decisions.

Implement Play Relax Weapon Animation Part 1
Fig 11.5.4.5.2 Play Relax Weapon Animation Part 1

We will start implementation with a sequence node with two execution tracks.  The "Then 1" track we will attach our return node to with "false" checked.  We use the sequence node as a fall back in case any condition pops up on the main line of execution that would cause our animations to not play (usually due to development miss configurations such as a missing animation).

Implement Play Relax Weapon Animation Part 2
Fig 11.5.4.5.3 Play Relax Weapon Animation Part 2

Now we will grab our "BP Combat Demo Weapon Manager" and pull a line to fetch the "Get Animation Set" function which returns our current "Animation Set" object. 

As any good programmer should, we validate the animation set first before trying to use it.  If this object is invalid then the execution will fall back to our sequence node that returns false allowing the proceed.

Then we draw a line out from the "Get Animation Set" function and call the "Get Ready Combat Montage" interface function.  You can draw a line from the "Hand Type" variable or right click and search for "Get Hand Type" and connect it to the "Hand Type" input parameter of the "Get Ready Combat Montage" node.  Finally connect the "Is Valid" execution path to the "Get Ready Combat Montage" node.

Implement Play Relax Weapon Animation Part 3
Fig 11.5.4.5.4 Play Relax Weapon Animation Part 3

Once again we validate the output of the "Get Ready Combat Montage" node.  If it is a valid asset execution will continue, other wise it will fall back to the "Sequence" node we created at the start and return false that no animation was played.

Now right click and search for "Play Anim Montage" and select it.  Feed the output of "Get Ready Combat Montage" node into the "Anim Montage"

Finally copy and paste or create a new return node and return true with it.

11.5.4.6 Play Next Weapon Relaxed Animation

Implement Play Next Relaxed Animation
Fig 11.5.4.6.1 Play Next Relaxed Weapon Animation

Paste Bin: Play Next Relaxed Weapon Animation

Click on and open the "Play Next Weapon Relaxed Animation".  This function is called by our Anim Notifies to play the next weapon relax animation.  It supplies the last weapon hand that was played so we can decide what hand to play next.  If we have played each hand then we can end the ready animation chain.

Implement Play Next Relaxed Animation Part 1
Fig 11.5.4.6.2 Play Next Relaxed Weapon Animation Part 1

As usual we will use a sequence node with two lines of execution.  Should a condition along the main execution line fail we will fall back to the "Then 1" execution and end the animation chain.

Grab a reference to the "BP Combat Demo Weapon Manager" and draw a line out to search for the functon "On Finished Relaxing Weapon".

Right click and search for "get Last Hand Type" to drop a new reference to the supplied "Hand Type" input or simply draw a line between it and the "Hand Type' input parameter of "On Finished Relaxing Weapon". 

Check true the parameter "Trigger Is Inactive".

Finally connect the "On Finished Relaxing Weapon" execution line to a Return node with the "Return Value" checked true.

Implement Play Next Relaxed Animation Part 2
Fig 11.5.4.6.3 Play Next Relaxed Weapon Animation Part 2

From the Sequence "Then 0" execution line create a Branch.

Then using the "Last Hand Type" input parameter we will need to do a convert to "EPncsStandardHandType".  Draw a line from "Last Hand Type" and search for "EPncsStandardHandType" and select "Byte to enum EPncsStandardHandType".  Then draw a line from the cast and search for "==" node.  Use the drop down to select the value "Main Hand".  If "Last Hand Type" does not equal the "Main Hand" then the "Off Hand" just finished and those are our only two hands for this system so we can end the ready animations sequence.

Implement Play Next Relaxed Animation Part 3
Fig 11.5.4.6.4 Play Next Relaxed Weapon Animation Part 3

After the Branch place a second branch.  We'll use this to check if the off hand weapon has a weapon set. 

Drop in a "BP Combat Demo Weapon Manager" node and draw a line from it to look for "Is Weapon Set".  This function checks if the given weapon has any sort of weapon data.

Right click on the graph and search for "EPncsStandardHandType" and choose "Literal enum EPncsStandardHandType" from the list.  Set the value to "Off Hand" and feed it into the "Hand Type" input parameter of the "Is Weapon Set" node.

Connect the return value of the "Is Weapon Set" node to the input "Condition" of the branch.

Implement Play Next Relaxed Animation Part 4
Fig 11.5.4.6.5 Play Next Relaxed Weapon Animation Part 4

Now right click and search for "Play Relax Weapon Animation" and select it or drag it in from the list of interface functions.  Use the Enum Literal we created earlier and drag a line from it into the "Hand Type" of the "Play Relax Weapon Animation".  This will trigger our off hand weapon to play it's ready animation.  If you want to add more than two weapon hands to your game you would need to do something similar for each additional hand.

Now put down the last Branch.  This branch will check if the return value of "Play Ready Weapon Animation" was true (meaning it successfully started playing the animation).  If it is false something happened in that function where we could not play the desired animation for the hand (usually a missing animation from the animation set or the Animation Data that populates the set).  So as a final fall back we will use this branch.  In my design I have opted to simply allow it to fall back to "On Finished Relaxing Weapons" but you may print out a string for errors or trigger the next weapon animation (if you have more than two hands).

Finally connect the "True" execution line of the branch to a return node with "Return value" checked on to true.

11.5.4.7 On Finished Readying All Weapons

Implement On Finished Readying All Weapons
Fig 11.5.4.7.1 On Finished Readying All Weapons

Now open up the "On Finished Readying All Weapons" interface function.  Depending on the design of your combat system you may make use of this function.  For instance in our design our ready animation for being unarmed is just a single animation that plays which brings up both hands at the same time.  For this reason the animation calls an Anim Notify which then calls this function to switch the Weapon Manager into form it's "Readying" state to it's "Ready" state.

We will implement by getting a reference to "BP Combat Demo Weapon Manager" and dropping it onto the graph.  Then draw a line and look for the function "On Finished Readying Weapons" which is a native function of the weapon manager.

Connect the execution lines and return true.

11.5.4.8 On Finished Relaxing All Weapons

Implement On Finished Relaxing All Weapons
Fig 11.5.4.8.1 On Finished Relaxing All Weapons

Open up the "On Finished Relaxing All Weapons" interface function.  Depending on the design of your combat system you may make use of this function.  For the design of this combat system the relax animation for being unarmed is a simple animation taht drops both arms at the same time.  Beause of this the animation calls an Anim Notify which triggers this function to switch the Weapon Manager from it's "Relaxing" state to it's "Inactive" state.

To implement this function drop a reference to the "BP Combat Demo Weapon Manager" onto the graph.  Then draw a line and look for the function "On Finished Relaxing Weapons" which is a native function of the weapon manager.

Connect the execution lines and return true.

Back to Top

11.6 Implement BPI Demo Character

We are now at the final peice of setting up our character, implementing our customized character interface we created in Blueprints.

Expand BPI Demo Character Category
Fig 11.6.0.1 Expand BPI Demo Character Category

11.6.1 States

We will implement the "States" category of functions first. These functions are generally used to get some state information about our character.

11.6.1.1 Is Active Blocking

Is Active Blocking
Fig 11.6.1.1 Is Active Blocking

You can Open up "Is Active Blocking" if you want but their is no need.  We will be overriding this function later in the "Combat Manager" tutorial and the "Action Manager" tutorial.  For now you can keep it simply returning false.

11.6.1.2 Is Stunned

Is Stunned
Fig 11.6.1.2 Is Stunned

You can Open up "Is Stunned" if you want but their is no need.  We will be overriding this function later in the "Combat Manager" tutorial and the "Action Manager" tutorial.  For now you can keep it simply returning false.

11.6.1.3 Is Ranged Weapon

Is Ranged Weapon
Fig 11.6.1.3.1 Is Ranged Weapon

Paste Bin: Is Ranged Weapon

Open up the "IsRangedWeapon" function.  This function will determine if our character is currently equipped with a ranged weapon.  By the design of our combat system we assume that ranged weapons are two handed and therefore only the main hand will have the ranged weapon.

To implement this functionwe start with a sequence node with two execution lines.  From the "Then 1" we connect the "Return Node" with a false value returned in the "Is Ranged Weapon" output parameter.

Is Ranged Weapon Part 1
Fig 11.6.1.3.2 Is Ranged Weapon Part 1

Then we grab the "BP Combat Demo Weapon Manager" and pull a line to search for "Get Main Hand Weapon".  Like all good programmers we check that it is valid with an "Is Valid" node.

Is Ranged Weapon Part 2
Fig 11.6.1.3.3 Is Ranged Weapon Part 2

From the "Get Main Hand Weapon" node pull out another line and search for "Get Weapon Type". 

You will first need to convert it to the proper enum.  Draw a line from the output of "Get Weapon Type" and search for "EPncsStandardWeaponType" and choose "Byte to Enum EPncsStandardWeaponType". 

Now drag a line out from our convertion node and search for "==" and choose "Equal (Enum)".

Use the dropdown on the second input pin and choose "Ranged".  Then connect the output boolean value of the "==" node to the second return node.  You can copy and paste in a new return node or right click on the graph and search for "Return Node" to select "Add Return Node" from the list.

11.6.1.4 Get Hand Type From Combo Number

Get Hand Type From Combo Number
Fig 11.6.1.4 Get Hand Type From Combo Number

Open up the "Get Hand Type from Combo Number" function.  This is a handy utilty function we will leverage later in our combat system.  By the design of our combat system we have a total of two different strikes.  For Unarmed attacks it is a right hand punch and then a left left hand punch. For Melee weapons we have swing left and a swing right.  For more advanced combat systems we may need to know which hand or direction our attack came from and we can leverage the current combo number

To implement this function we will use a simple "Switch on Int".  You can add this node to the graph by drawing a line from our "Combo Number" input parameter and searching for "Switch" or by just right clicking and searching for "Switch on Int". 

Click on the "add Pin" button 3 times to add the execution lines for 0, 1, and 2.

Add a second return node by copying and pasting the original return node or by right clicking on the graph and searching for "Return" and choosing "Add Return Node".

Set one return node to "Main Hand" and the other to "Off Hand".

Connect the 0, 2, and Default execution lines top the "Main Hand" return node

Connect toe 1 execution line to the "Off Hand" return node.

11.6.1.5 Is Precision Demo

Is Precision Demo
Fig 11.6.1.5 Is Precision Demo

This next part is purely for the demo purposes because later we will will setup a Precision System Demonstration and I do not want certain things from other demos to get in the way.  Do not worry this will become clear later, for now we leave this as it is because we are not working with a Precision Demo Character.

Back to Top

11.6.2 Stats

Now we implement the "Stats" category.  This group is pretty straight forward as we will only care about "HP" for our combat system.

11.6.2.1 Get Health

Get Health
Fig 11.6.2.1 Get Health

Click on the "Get Health" function to open it.  This function simply returns the current rating of our character's health.  We would leverage this interface function in our UI system to fetch the current health of our character or enemy and display it on the screen.

To implement this we simply drag the "Current Health" value we created earlier onto the graph as a "Get" and plug it into the "Health" output parameter.

11.6.2.2 Get Total Health

Get Total Health
Fig 11.6.2.1 Get Total Health

Now click on the "Get Total Health" interface function to open it.  This function simply returns the maximum health our character can have, we defaulted it to 100 for simplicity sake.  Again we would leverage this in our UI system to show how much health we have lost or even calculate a percentage of health lost.

To implement this function we drag the "Max Health" variable we created earlier onto the graph as a "Get" and plug it into the "Total Health" output parameter of the function.

Back to Top

11.6.3 Animations

This section we will implement the "Animation" category.  This group represents our custom animations we will be using for our combat system. We will go into a different tutorial on how to setup these animations.  For now I will do my best to give a high level explaintion on how they work.

If you are working from the Starting project download you can take a peek at how the Animation Montage's are setup.  I highly suggest looking at how the Anim Montage's are setup for Hand to Hand (H2H), Melee, and the Bow weapons

11.6.3.1 Play Attack Animation

Play Attack Animation
Fig 11.6.3.1.1 Play Attack Animation

Paste Bin: Play Attack Animation

First we will setup our attack animation.  This will be the function that gets called when we want to execute an Attack montage.  As noted above I suggest looking at how the "AM_H2H_Attack_Demo" and "AM_Melee_Attack_Demo" montage's are setup.  These montage's have a few defined sections that we can jump to in our animations.  Each have a Default, Attack_1, Attack_2, A1_Cooldown, A2_Cooldown, A1_End, and A2_End section.  When an attack is triggered it will play the Attack and loop the Cooldown sections until the End section is called by the system when a combo sequence has ended.

Implement Play Attack Animation Part 1
Fig 11.6.3.1.2 Implement Play Attack Animation Part 1

To implement this function we begin with a Sequence node with two execution lines.

From the "Then 1" execution line connect a Return Node that returns false as the "Is Playing" return value.

Implement Play Attack Animation Part 2
Fig 11.6.3.1.3 Implement Play Attack Animation Part 2

Now get the "BP Combat Demo Weapon Manager" and draw a line from to search for "Get Animation Set". 

As all good programmers we validate the animation Set is not null.

Connect the "Then 0" execution line from the previous sequence node to the Is Valid Node.

Then draw a line from the return value of the "Get Animation Set" node and look for the "Get Attack Montage" form the "BPI Demo Aniamtion Data" interface.

Connect the "Is Valid" execution line from the Is Valid Node to the "Get Attack Montage" interface function.

Once again check that returned montage from "Get Attack Montage" node is a valid object.

Implement Play Attack Animation Part 3
Fig 11.6.3.1.4 Implement Play Attack Animation Part 3

Right click on the graph and look for "Combo Number" and select "Get Combo Number" or draw a line from the "Combo Number" input variable for this function. 

From "Combo Number" draw a line and look for "Switch On Int" and select it.

Click on "Add Pin" 3 times to create 0, 1, and 2 execution pins.  This will work similar to our "Get Hand Type from Combo Number".

Right click on the graph and select "Play Anim Montage".  Copy and paste 3 of these nodes onto the graph.

From the "Get Attack Montage" interface node draw a line and connect it to all 3 of the "Play Anim Montage" nodes.

In the "Start Section Name" of the first node leave it blank.  In the "Start Section Name" of the second node set it to "Attack_2" and "Attack_1" in the third node.

Now Connect the "0" and Default execution lines of the "Switch on Int" node to the First "Play Anim Montage" (the one with the blank "Start Section Name").

Now Connect the "1" execution line to the second "Play Anim Montage" node (the one set to "Attack_2" in the "Start Section Name").

Now Connect the "2" execution line to the second "Play Anim Montage' node (the one set to "Attack _1" in the "Start Section Name").  We separate the "0" and "2" montages so that we can play a starting animation as the first attack and then a loop able attack for the first and second.  This becomes more important later during the Projectile Tutorial.

Finally connect each of the "Play Anim Montage" nodes to a "return node" with "Is Playing" checked true

11.6.3.2 Play End Attack Animation

Play End Attack Animation
Fig 11.6.3.2.1 Play End Attack Animation

Paste Bin: Play End Attack Animation

Open up the "Play End Attack Animation" interface function.  This function is called when the combo number resets to 0 ending the current chain of attacks.  It plays an ending animation to put the character back into a ready but neutral stance.  This is most important for the bow weapon where we will allow for continuous nocking of arrows and firing and we will need an animation that lowers the bow after a few seconds of not firing.

As noted above I suggest looking at how the "AM_H2H_Attack_Demo" and "AM_Melee_Attack_Demo" montage's are setup.  These montage's have a few defined sections that we can jump to in our animations.  Each have a Default, Attack_1, Attack_2, A1_Cooldown, A2_Cooldown, A1_End, and A2_End section.  When an attack is triggered it will play the Attack and loop the Cooldown sections until the End section is called by the system when a combo sequence has ended.

Implement Play End Attack Animation Part 1
Fig 11.6.3.2.1 Implement Play End Attack Animation Part 1

This funciton will be implemented similarly to the "Play Attack Animation" function in that we will leverage the current combo nuber to choose what ending animation to play.  For instance if we swing a sword to the left we will play an ending animation that drops the sword from the left side and from the right side if we have swung it to the right.

Start implementing this function with our usual sequence node with two execution lines.  Draw a line from the second execution node "Then 1" and connect it to a return node with "Is Playing" unchecked or false.

Implement Play End Attack Animation Part 2
Fig 11.6.3.2.3 Implement Play End Attack Animation Part 2

Drop a reference to the "BP Combat Demo Weapon Manager" and draw a line to search for "Get Animation Set". 

Like all good devleopers use an "Is Valid" macro node to check if the retrieved Animation Set object is valid.

Now Draw a line from the return of "Get Animation Set" and search for the function "Get Attack Montage".

Again like any good developer use the "Is Valid" macro to check if the retrieved Montage is not empty or null.

Implement Play End Attack Animation Part 3
Fig 11.6.3.2.4 Implement Play End Attack Animation Part 3

Right click on the graph and look for "Get Combo Number" to put a get node to the input parameter "Combo Number".  You can also draw a very long line out from the input parameter at the starting node of the function.

From the "Combo Number" node draw out a line and search for "Switch on Int".

Click on the "Add pin" button 3 times.

Right Click on the graph and search for "Play Anim Montage" and select it.

Create a second "Play Anim Montage" node by copying and pasting the previous one or repeat the previous step.

From "Get Attack Montage" node draw a line out and connect it to the "Anim Montage" input pin of both the "Play Anim Montage" nodes.

In the first "Play Anim Montage" set the "Start Section Name" input parameter to "A1_End"

In the second "Play Anim Montage" set the "Start Section Name" input parameter to "A2_End"

Connect the "0", "2", and "Default' execution lines to the first "Play Anim Montage" node (the one with "A1_End" set in the "Start Section Name")

Connect the "1" execution line to the second "Play Anim Montage" node (the one with the "A2_End" set in the "Start Section Name")

Finally right click and search for "Return" and select "Add Return Node" to create a new return node or copy and paste the previous return node.  Check the return so that "Is Playing" is true.

Connect both "Play Anim Montage" nodes to the return node.

11.6.3.3 Play Start Guard Animation

Play Start Guard Animation
Fig 11.6.3.3.1 Play Start Guard Animation

Paste Bin: Play Start Guard Animation

[PASTEBIN: 11_Play StartGuardAnimation]

Open up the "Play Start Guard Animation" interface function.  This function is called to have your character start playing the guarding animation.  Our Guard animation montage has three sections.  A Default and a Loop section which this function will triger and start the guard and have the montage play a continuous loop to guard.  Then it has a Stop section for ending the animation.

Implement Play Start Guard Animation Part 1
Fig 11.6.3.3.2 Implement Play Start Guard Animation Part 1

To implement this we start with a sequence node with two execution lines.  From the "Then 1" execution line connect the return node with "is Playing" unchecked as false.

Implement Play Start Guard Animation Part 2
Fig 11.6.3.3.3 Implement Play Start Guard Animation Part 2

Now drop in a "BP Combat Demo Weapon Manager" node and draw a line to search for "Get Animation Set".

Like all good programmers we validate objects so right click and search for a "Is Valid" macro.  Connect the execution line from the previous "Then 0" sequence node to the "exec" input execution of the macro

Draw a line from "Get Animation Set" and search for "Get Guard Montage" from the "BPI Demo Animation Data" interface.

Once again validate that the returned montage is not null or empty.

Implement Play Start Guard Animation Part 3
Fig 11.6.3.3.4 Implement Play Start Guard Animation Part 3

Right click and search for "Play Anim Montage"

Connect the output from "Get Guard Montage" to the "Anim Montage" input parameter of the "Play Anim Montage" node.

Right click and search for "Return" to select "Add Return Node".

Connect the "Play Anim Montage" execution line to the new "Return Node" and make sure "Is Playing" output paraemter is set to true.

11.6.3.4 Play End Guard Animation

Play End Guard Animation
Fig 11.6.3.4.1 Play End Guard Animation

Paste Bin: Play End Guard Animation

Open up the "Play End Guard Animation" interface function.  This function is called to have your character stop playing the guarding animation.  Our Guard animation montage has three sections.  A Default and a Loop section will triger and start the guard animation and have the montage play a continuous loop to guard.  Then it has a Stop section that this function is responsible for starting to end the guard loop animation and drop the guard.

Implement Play End Guard Animation Part 1
Fig 11.6.3.4.2 Implement Play Start Guard Animation Part 1

To implement this we start with a sequence node with two execution lines.  From the "Then 1" execution line connect the return node with "is Playing" unchecked as false.

Implement Play End Guard Animation Part 2
Fig 11.6.3.4.3 Implement Play Start Guard Animation Part 2

Now drop in a "BP Combat Demo Weapon Manager" node and draw a line to search for "Get Animation Set".

Like all good programmers we validate objects so right click and search for a "Is Valid" macro.  Connect the execution line from the previous "Then 0" sequence node to the "exec" input execution of the macro

Draw a line from "Get Animation Set" and search for "Get Guard Montage" from the "BPI Demo Animation Data" interface.

Once again validate that the returned montage is not null or empty.

Implement Play End Guard Animation Part 3
Fig 11.6.3.4.4 Implement Play Start Guard Animation Part 3

Right click and search for "Play Anim Montage"

Connect the output from "Get Guard Montage" to the "Anim Montage" input parameter of the "Play Anim Montage" node.

In the "Play Anim Montage" node's input parameter "Start Section Name" set the value to "Stop".

Right click and search for "Return" to select "Add Return Node".

Connect the "Play Anim Montage" execution line to the new "Return Node" and make sure "Is Playing" output paraemter is set to true.

11.6.3.5 Play Attack Deflected Animation

Play Attack Deflected Animation
Fig 11.6.3.5.1 Play Attack Deflected Animation

Paste Bin: Play Attack Deflected

Open up the 'Play Attack Deflected Animation".  This function is called when the character's attack is deflected by a guarding character.  The Montage that plays simply plays to length and has root motion turned on which will help prevent the character from moving while it plays.  You can also implement in the input functions a test to see if the character is stunned, which is actually a better method of doing it that does not rely on root motion.  Once the animation finishes playing the character an act and move again.

Implement Play Attack Deflected Animation Part 1
Fig 11.6.3.5.2 Implement Play Attack Deflected Animation Part 1

We start implementation of this function like all other functions, a sequence node with two execution tracks.

From the second execution track "Then 1" of the sequence node connect a return node with the "Is Playing" output set to false or unchecked.

Implement Play Attack Deflected Animation Part 2
Fig 11.6.3.5.3 Implement Play Attack Deflected Animation Part 2

Now drop in a "BP Combat Demo Weapon Manager" node and draw a line to search for "Get Animation Set".

Like all good programmers we validate objects so right click and search for a "Is Valid" macro.  Connect the execution line from the previous "Then 0" sequence node to the "exec" input execution of the macro

Draw a line from "Get Animation Set" and search for "Get Deflection Montage" from the "BPI Demo Animation Data" interface.

Once again validate that the returned montage is not null or empty.

Implement Play Attack Deflected Animation Part 3
Fig 11.6.3.5.4 Implement Play Attack Deflected Animation Part 3

Right click on the graph and search for "Play Anim Montage"

Connect the output from "get Deflection Montage" to the "Anim Montage" input parameter of the "Play Anim Montage" node.

Right click and search for "Return" to select "Add Return Node".

Connect the "Play Anim Montage" execution line to the new "Return Node" and make sure "Is Playing" output paraemter is set to true.

Back to Top


12 Player Controller

Now we need to implement our player controller.  For the combat system this is very simple.

Open the Player Controller Blueprint
Fig 12.0.1 Open Player Controller

Start by opening the BP_DemoPlayerController.

Add the Interface
Fig 12.0.2 Add the Interface

Click on the "Class Settings".

Under the "Interfaces" section of the "Details" panel click on the "Add" button and add the "IPncs Unified Controller Pawn" interface.

12.1 Implement Unified Controller Pawn

Now we will implement the Unified Controller Pawn Interface for the Player Controller. 

Back to Top

12.1.1 Get Pawn

Get Pawn (PNCS)
Fig 12.1.1 Get Pawn (PNCS)

Double Click and open "Get Pawn (PNCS)" to edit it.

To implement this function we will simply use the "Get Controlled Pawn" function which is a native function of the Controller class.

12.1.2 Get Controller

Implement Get Controller
Fig 12.1.2 Implement Get Controller

Now open "Get Controller (PNCS)".

To implement this function we will simply return a reference to "self".

12.1.3 Is Controlled Player (PNCS)

Implement Is Controlled Player (PNCS)
Fig 12.1.3 Implement Is Controlled Player (PNCS)

Now open "Is Controlled Player (PNCS)".

To implement this function we will simply return true. This means that on client machines it will only return true for the one and only controller that exists on the connected clients, but on the server all Player Controllers will return true


13 Animation Blueprint

We are finally coming to a close for this first tutorial and the final section is setting up our Animation Blueprint for our character to use.   I will give a bit of a fair warning, this is not an optimal way of implementing an Animation Blueprint.  There are still plenty of tricks you and your animation expert can and should do to optimize how the animation systems in your game work especially if you are building an open world game.  For instance most of the property changes are querried each tick from the character, you can easily change this to update only at the startup of the Animation Graph or when the weapon properties change on the character.  Also as a general principal of mine I never replicate (network) animation blueprints, my general philosophy is that the character drives the values of the animation blueprint which is querried from the character in the Animation Blueprint Event Graph.

Add Variables
Fig 13.1.1 Add Variables

Earlier we duplicated the Anim Blueprint of the Third Person Blueprint and renamed it to "ABP_DemoCharacter".  Go to "Mannequin/Animations" and open up the "ABP_DemoCharacter" Animation Blueprint.

Back to Top

13.1 Setup Variables

Open Animation Blueprint
Fig 13.0.1 Open Animation Blueprint

We will start by defining the variables we will need.

13.1.1 References

We will define the references we need first, these are objects and components our animation system will leverage to query data from. These variables will be under the "References" category.

Property Name Type Default
Weapon Manager Pncs Weapon Manager Base None
  Reference to the owning character's Weapon Manager Component
 
AnimationSet Pncs Animation Set Base None
  Reference to the Animaton Set Object that will hold the combat animations
 

13.1.2 State

Now we define the "State" category of variables.  A few of these will already exist, we will simply move them into the State Category.

Property Name Type Default
IsMovingAndOnGround boolean False
  Flag indicates that the character is moving along the ground as apposed to jumping and falling
 
IsCombatReady boolean False
  Flag indicating that our character is currently in a combat ready state.
 

13.1.3 Default Anims

The "Default Anims" state holds the default animations our character will play in the event that the "Animation Set" is invalid or empty or the animation property the Animation Set holds is null for some reason.

Property Name Type Default
DefaultIdleSequence Anim Sequence Base ThirdPersonIdle
  Idle Animation to play by default
 
DefaultMovementBlendspace Blend Space Base ThirdPerson_IdleRun_2D
  Movement Blendspace to use by default
 
DefaultJumpStartSequence Anim Sequence Base ThirdPersonJump_Start
  Default Jump Start animation to use
 
DefaultJumpLoopSequence Anim Sequence Base ThirdPersonJump_Loop
  The default jump loop animation sequence to use.
 
DefaultJumpEndSequence Anim Sequence Base ThirdPersonJump_End
  Default Jump end Animation to use.
 

 13.1.4 Active Anims

The "Active Anims" state holds the current animations our character will play which are initially stored in the "Animation Set" is object.  Yes you can just duplicate each variable from the "Default Anims"

Property Name Type Default
IdleSequence Anim Sequence Base None
  Idle Animation to play
 
MovementBlendspace Blend Space Base None
  Movement Blendspace to play for moving
 
JumpStartSequence Anim Sequence Base None
  Jump Start animation to use
 
JumpLoopSequence Anim Sequence Base None
  The jump loop animation sequence to use.
 
JumpEndSequence Anim Sequence Base None
  Jump end Animation to use.
 

Back to Top

13.2 Setup Functions

Now we will setup a few utility functions that will handle our updates during game play.

13.2.1 Ensure References

Ensure References
Fig 13.2.1.1 Ensure References

Paste Bin: Ensure References

First we will setup the "Ensure References" function which will update and maintain the references of our animation system.

Under "My Blueprint" find the "Functions" tab and click on the "+" button.  Name the new function "Ensure References" and give it the category "Custom".  We are not going to create inputs or outputs for this function.

Implement Ensure References Part 1
Fig 13.2.1.2 Implement Ensure References Part 1

Grab and drop a Git node for "Weapon Manager" variable we created earlier.  Then Right click it and choose "Convert to Validated Get".  If our Weapon Manager is not empty or null we can continue with this function along the "Is Valid" execution line, otherwise we are going to go to the "Is Not Valid" Execution line.

Right click on the graph and look for "Get Owning Actor" and select it.

From "Get Owning Actor" draw a line and look for "Get Weapon Manager" function from the "PNCS Weapon Owner" interface.

As usual because we are good developers we validate that the Weapon Manager is valid.

Now Drop a Get "Weapon Manager" node onto the graph or right click and search for "Get Weapon Manager" and select it. 

Draw a line from "Get Weapon Manager" return value to the input of "Set Weapon Manager" node.

Once again check that the weapon manager itself is valid, it should be if we have the proper character type.

Implement Ensure References Part 2
Fig 13.2.1.3 Implement Ensure References Part 2

Now Drop a Get for "Animation Set" or right click and search for the "Get Animation Set" variable we created earlier.

Right click on the Get node "Animation Set" and select "Convert to Validated Get".  If the Animation Set is already set than we can simply stop executing this function now.  Other wise we will fetch the animation set from the weapon manager.

Connect the "Is Valid" execution line from the validated "Get Weapon Manager" node to the validated "Get Animation Set" node. 

Then connect the "Is Valid" execution line from the "Is Valid" macro tha tvalidted our "Set Weapon Manager" node.

Drop a "Get Weapon Manager" node onto the graph.

Then draw a line from the "Get Weapon Manager" node and look for "Get Animation Set".

Drop a "Set Animation Set" node onto the graph.

Connect the "Is Not Valid" execution line of the validated "Get Animation Set" and connect it to "Set Animation Set".

Now draw a line from "Get Animation Set" node and connect it to the input pin of "Set Animation Set" node.

If you are wondering we do not need to validate our Weapon Manager or the Get Animation Set node we pulled from it because we have already done that with the previous two validated get nodes.

13.2.2 Is Moving On Ground

Is Moving and On Ground
Fig 13.2.2.1 Is Moving And On Ground

This function will be used to update our "Is Moving On Ground" variable which will be updated in the event graph.  It is pretty straight forward as we already have an "Is In Air" property that is updated in the event graph.

Create a new function and call it "Is Moving On Ground" and put it in the "Custom" category.

Click on first node labled "Is Moving On Ground" and then go to the "Details Panel".  Check "Pure" and "Const" to make this function a pure and const function.

Add a boolean output property called "Is Moving" to the function.

Grab a Get "Is In Air" node and drop it on the graph. 

Then drop a "Branch" next to it.

Connect the "True" execution line of the branch to a return node that returns false.

Then grab a get "Speed" node and drop it onto the graph.  Draw a line from the output of speed and search for ">" (greater then).  In the second input set it to "0.5".

Add a new return node and connect the output of the greater then to the output of the return node.

Draw a line from the "False" execution line to the second return node.

13.2.3 Update Variables

Update Variables
Fig 13.2.3.1 Update Variables

Create a new function called "Update Variables" and give it the "Custom" category.  This function will update our Animation Blueprint Variables we created earlier.

Place in a sequence node with two execution lines.

Grab and drop our "Is Moving On Ground" function.

Drop a Set "Is Moving And On Ground" node on the graph and connect the "Is Moving On Ground" return node into the input node of the set "Is Moving and on Ground" node.

Now drop a get "Weapon Manager" node on the graph and right click on it to select "Convert to Validated Get".

Draw a line from "Then 1" to the validated get "Weapon Manager" node.

From the return value of get "Weapon Manager" draw a line and search for "Is Combat Mode Enabled".

Drop a set "Is Combat Ready" node on to the graph.

From the validated get "Weapon Manager" draw a line from the "Is Valid" execution line to the input execution line of the set "is Combat Ready"

Then from the "Is Combat Mode Enabled" node draw a line from the output to the set "Is Combat Ready".

13.2.4 Update Animations

Update Animations
Fig 13.2.4.1 Update Animations

Paste Bin:Update Animations

Create our last function "Update Animations".  This function will pull the animations from the Animation Set to update the animations we will be using for the combat system animations.

Implement Update Animations Part 1
Fig 13.2.4.1 Implement Update Animations Part 1

Drop in a get "Animation Set" node and then right click and select "Convert to Validated Get".  If this object is null than we cannot update our animations.

From the Validated get "Animation Set" draw a line and search for "Get Idle Sequence" from the BPI Demo Animation Data.

Like all good programers we validate that our unknowns are valid and check the return "Idle Sequence" to be valid.  If the return of "Get Idle Sequence" is valid then we will set it to the "Idle Sequence " variable we created.

Drop two set "Idle Sequence" nodes on the graph and connect the "Is Valid" execution path to one of them and the "Is Not Valid" execution path to the other.

Then Draw a line from the return value of "Get Idle Sequence" to the set "Idle Sequence" on the "Is Valid" execution path.

Now drop a get "Default Idle Sequence" node on the graph and connect it to the set "Idle Sequence" node on the "Is Not Valid" execution path.

Implement Update Animations Part 2
Fig 13.2.4.3 Implement Update Animations Part 2

From here on I will be very brief in my descriptions as the remaining parts of this function are nearly copy and paste with a few alterations to the nodes we are using.

Drop a get "Animation Set" on the graph and draw a line to search for "Get Movement Blend Space".

Connect the two set "Idle Sequence" execution paths to the "Get Movement Blend Space" node.

Validate the Blend Space.

Add two set "Movement Blend Space" nodes on the graph and connect the "Is Valid" and "Is Not Valid" execution paths to each one.

Connect the output of get "Movement Blend Space" to the Valid Set.

Drop a get "Default Movement Blend Space" on the graph for the "Is Not Valid" and connect the output pin to the input pin of the set "Movement Blend Space" node.

Implement Update Animations Part 3
Fig 13.2.4.4 Implement Update Animations Part 3

Drop a get "Animation Set" on the graph and draw a line to search for "Get Jump Start Sequence".

Connect the two set "Movement Blend Space" execution paths to the "Get Jump Start Sequence" node.

Validate the Sequence.

Add two set "Jump Start Sequence" nodes on the graph and connect the "Is Valid" and "Is Not Valid" execution paths to each one.

Connect the output of get "Jump Start Sequence" to the Valid Set.

Drop a get "Default Jump Start Sequence" on the graph for the "Is Not Valid" and connect the output pin to the input pin of the set "Jump Start Sequence" node.

Implement Update Animations Part 4
Fig 13.2.4.5 Implement Update Animations Part 4

Drop a get "Animation Set" on the graph and draw a line to search for "Get Jump Loop Sequence".

Connect the two set "Movement Blend Space" execution paths to the "Get Jump Loop Sequence" node.

Validate the Sequence.

Add two set "Jump Loop Sequence" nodes on the graph and connect the "Is Valid" and "Is Not Valid" execution paths to each one.

Connect the output of get "Jump Loop Sequence" to the Valid Set.

Drop a get "Default Jump Loop Sequence" on the graph for the "Is Not Valid" and connect the output pin to the input pin of the set "Jump Loop Sequence" node.

Implement Update Animations Part 5
Fig 13.2.4.6 Implement Update Animations Part 5

Drop a get "Animation Set" on the graph and draw a line to search for "Get Jump End Sequence".

Connect the two set "Movement Blend Space" execution paths to the "Get Jump End Sequence" node.

Validate the Sequence.

Add two set "Jump End Sequence" nodes on the graph and connect the "Is Valid" and "Is Not Valid" execution paths to each one.

Connect the output of get "Jump End Sequence" to the Valid Set.

Drop a get "Default Jump End Sequence" on the graph for the "Is Not Valid" and connect the output pin to the input pin of the set "Jump End Sequence" node.

Back to Top

13.3 Event Graph

The Event Graph
Fig 13.3.1 Event Graph

Next we will setup the Event Graph to update the properties of our Animation Blueprint.

I did a tiny bit of rework on the Event Graph to clean it up a bit.

The Event Graph
Fig 13.3.2 Event Graph

Ultimatley we are just going to drop 3 of our functions we created along the execution line from the set "Speed" node.

Add "Ensure References" and connect it to "Update Variables" and finally to "Update Animations".

Back to Top

13.4 Anim Graph Locomtion

Now we will adjust the Animation Graph to leverage our Animaiton Set and combat modes.

The Anim Graph
Fig 13.4.1 Anim Graph

We will start with the "Default" State Machine.  I will be renaming this state machine to "Locomotion" you can do the same or create a new state machine named "locomotion" and follow along. We will be reusing the nodes within "Default" so be sure to not delete them.

Move Default States Out of the Way
Fig 13.4.2 Move Default States out of the way

Double click on "Default" to open it.  Move the four animation states out of the way for now.

Create States
Fig 13.4.3 Create States

From the "Entry" node draw a line to create a new state and call it "Movement"

Then draw a line from the "Movement" state ceate another new state and call it "CombatMovement"

Finally draw a line back from the "Combat Movement" state to the "Movement" state.

Edit Combat Transition
Fig 13.4.4 Edit Transition

Double click on the transition from "Movement" to "CombatMovement" states.

Setup Combat Transition
Fig 13.4.5 Setup Combat Transition

Drop a get "Is Combat Ready" node onto the graph and connect it to "Can Enter Transition".

Edit MovementTransition
Fig 13.4.6 Edit Movement Transition

Go back to the Locomotion state graph and double click on the transition from "CombatMovement" to "Movement"

Setup MovementTransition
Fig 13.4.7 Setup Movement Transition

Drop a get "Is Combat Ready" node onto the graph and then draw a line from the "Is Combat Ready" node to serch for a "Boolean Not".

Plug the output from the "boolean Not" into the "Can Enter Transition" node.

Cut or Copy the Default States
Fig 13.4.8 Cut or Copy the Default States

Now Cut or Copy the 4 original nodes and their transitions in Blueprint.  This includes "Idle/Run", "JumpStart", "JumpLoop", "JumpEnd" as well as "Transition to JumpStart", "Transition To JumpLoop", "Transition to Jump End" and "Transition to Idle/Run".  We'll reuse these in a moment so hold them in your copy buffer for now.

Open the Movement State
Fig 13.4.9 Open the Movement State

Double click on "Movement" state to open it.

Create the Movement State Machine
Fig 13.4.10 Create the Movement State Machine

Right click on the graph and search for "State Machine" and select "Add New State Machine".

Name the new State machine "Movement State".  This state machine will be our non-combat states for movement.

Paste Nodes
Fig 13.4.11 Paste Nodes

Double click to enter the "Movement States" state machine.  Hopefully you have not cleared your copy buffer.  Paste the 4 original nodes and their transitions into this state machine.

Connect the "Entry" node to the "Idle/Run" node.

And that's a job done for this state machine.

Open Combat Movement
Fig 13.4.12 Open Combat Movement

Now Double click on the "Combat Movement" state.  We are essentually going to do the same thing here we did to the regular movement state.

Create Combat Movement State Machine
Fig 13.4.13 Create Combat Movement State Machine

Rght click and search for "State machine" to select "Add New State Machine".

Name this State machine "Combat Movement States".

Paste State Nodes
Fig 13.4.14 Paste State Nodes

Double click and enter the "Combat Movement States" state machine.

Again hopefully you have not cleared your copy buffer.  Paste in the same 4 movement states and their transitions as before.

Connect the Entry node to the "Idle/Run" state.

Now here I went through and gave each state their own unique name by adding "Combat" to the front of the state.  This is optional as it should work just fine as it is.  However this is where we will start making the changes for combat animations. The transitons themselves will remain the same and need not alterations but the nodes will be changed.

Open Combat Idle/Run
Fig 13.4.15 Open Combat Idle/Run

Double click and open "Combat Idle/run" state.

Edit Combat Idle/Run
Fig 13.4.16 Edit Combat Idle/Run

You'll see the blendspace player with a "speed" variable connected to the "X" input of the player.

Select the "Blendspace Player" node and in the "Details" panel and put a check on the "Blend Space" property. This will allow us to connect our custom blendspace variable as input.

Connect Blend Space
Fig 13.4.17 Connect Blend Space

Drag the "Movement Blend Space" variable onto the graph and connect it to the "Blend Space" node that should now be available.

Open Combat Jump Start State
Fig 13.4.18 Open Combat Jump Start State

Now go back to the "Combat Movement State" graph and double click on "Combat Jump Start" state to edit it.

Edit Combat Jump Start State
Fig 13.4.19 Edit Combat Jump Start State

You'll see an Animation Sequence Player connected to the Output Animation Pose.

Click on the Animation Sequence Player and in the "Details" panel click the check mark on "Sequence" to allow an input for what sequence we will be playing.

Drag our variable "Jump Start Sequence" onto the graph and connect it to the new input node.

Open Combat Jump Loop State
Fig 13.4.20 Open Combat Jump Loop State

Now go back to the "Combat Movement State" graph and double click on "Combat Jump Loop" state to edit it.

Edit Combat Jump Loop State
Fig 13.4.21 Edit Combat Jump Loop State

You'll see an Animation Sequence Player connected to the Output Animation Pose.

Click on the Animation Sequence Player and in the "Details" panel click the check mark on "Sequence" to allow an input for what sequence we will be playing.

Drag our variable "Jump Loop Sequence" onto the graph and connect it to the new input node.

Open Combat Jump End State
Fig 13.4.22 Open Combat Jump End State

Now go back to the "Combat Movement State" graph and double click on "Combat Jump End" state to edit it.

Edit Combat Jump End State
Fig 13.4.23 Edit Combat Jump End State

You'll see an Animation Sequence Player connected to the Output Animation Pose.

Click on the Animation Sequence Player and in the "Details" panel click the check mark on "Sequence" to allow an input for what sequence we will be playing.

Drag our variable "Jump End Sequence" onto the graph and connect it to the new input node.

Back to Top

13.5 Anim Graph Montage Blending

In this next segment we will be blending any attack or action montages with our Locomotion Animations.

Cache Locomotion Pose
Fig 13.5.1 Cache Locomotion Pose

Return to the top level of the AnimGraph.

Disconnect the "Default" State Machine and rename it to "Locomotion".

Then Drag a line from the pose line and search for "cache" and select "New Saved Cached Pose"

Name the new pose cache "LocomotionPose"

Add a Layered Blend Per Bone Node
Fig 13.5.2 Add a Layered Blend Per Bone Node

Now we will be running our cached locomotion poses through the Anim Montage Slots.  The first will be the upper body slot that has been setup on may of the attack montages in order to perform attacks and blend the attack animations with the movement animations.  The art of blending Attacks with movement can be tricky, and just as a for warning I did not take a lot of time to tweek these animations and get them to look great, all I wanted was a passable animation.  Because of this, some things may not exactly be perfect.

Right click on the AnimGraph and search for "Layered Blend Per Bone" and place it on the graph.

Click on the node and in the "Layer Setup" and the "0" element.  Add a new member to it.  Then Expand it and add a new element to "Branch filteres".

Expand Branch filters.  In the "Bone Name" set it to "spine_01" or what ever the bone just above the pelvis is for your character.

Then set the "Blend Depth"  to 3.

What this does is starting at the bone just above the pelvic bone (in this case spine_01).  We blend our attack animation up the next three bones until it is 100% the attack animation.  This improves the overall apperance of the attack animation, but most importantly we will only do this kind of blending while the character is moving.

Find Cached Locomotion Pose
Fig 13.5.3 Find Cached Locomotion Pose

On the left hand side of our "Layered Blend Per Bone" node right click and search for "cache" and select "Use Cached Pose LocomotionPose".

Setup Layered Attack Blend
Fig 13.5.4 Setup Layered Attack Blend

Connect the "Use Cached pose 'LocomotionPose' " node to the "Base Pose" of the "Layered blend per bone" node.

Then copy the "Use cached pose 'LocomotionPose' " and paste a second one to the graph.

Right click and search for "Slot" and select "slot 'DefaultSlot'" node.

Configure the Slot Node
Fig 13.5.5 Configure the Slot Node

Click on the "Slot 'DefaultSlot'" and in the "Details" Panel change the "Slot Name" property to the "Body.Upper" slot.  This is one of the special slots I setup for the montage animations.  You may have different slot names you want to use and that is dependent upon your own development choices.

This may seem weird but what it basically does is take the cached "locomotionPose" and blends it with any Montage animation playing in the "Body.Upper" slot.  This is now our Moving and Attacking Animation.

Setup Non Moving Montage Blending
Fig 13.5.6 Setup Non Moving Montage Blending

Now that we have our Moving and Attacking Animaiton I want to play the full Montage from head to toes if we are not moving. So now we will use our Moving and Attacking animation we just blended and select either it or the just the full montage animation.

To the right of the "Layered Blend Per Bone" node right click and look for "Blend Poses By Bool" and select it.

We'll use the boolean we created "Is Moving and On Ground".  Drag a get "Is Moving and On Ground" node onto the animation graph and connect it to the "Active Value" of the "Blend Poses By Bool".

From the "Layered Blend per bone" node drag an execution line from it and connect it to the "True Pose" of the "Blend Poses by Bool".

Then copy and paste a "Use cached pose 'LocomoitonPose' " on the graph.

Draw a line from the "Use cached pose 'LocomotionPose' " and look for "Slot" to select "Slot 'DefaultSlot' " node.

Select the "Slot 'DefaultSlot' " node and in the "Defaults" Panel set the "Slot Name" to "Body.Upper".

Connect the "Slot 'Upper' " to the "False Pose"

Now take the output of "Blend Poses by bool" and search for cache and select "New Saved cached Pose"

Set the name of the new cached pose to "UpperBodyPose".

I chose "Upper Body Pose" as the name because in theory I can use that same slot to represent things like emotes and not just attacks.

Setup Full Body Montage Blending
Fig 13.5.7 Setup Full Body Montage Blending

Now we are almost finished. We will perform one more montage slot blend to blend "full body" montages that need to play on the full body of the character.  This one is a lot simplier.

Right click and search for "cache" to select "Use cached pose 'UpperBodyPose' ".

Then right click and search for "Slot" to select "Slot 'DefaultSlot' ".

Click on the slot node and in the "Details" panel change it's "Slot Name" property to "Body.Full".

Now Cache the pose as "Final Pose".

Setup the Output Pose
Fig 13.5.7 Setup The Output Pose

The final thing to do is plugin our "Final Pose" cached animation directly into the "output Pose"

You could just skip the final pose caching and directly feed the blended nodes for full body into the "Output Pose" node as well.

Back to Top

14.0 Outro

That is all for this tutorial.  We have finished setting up the foundation for all other tutorials for the combat system demonstration.  In the next two tutorials we will be implementing our combat system.  One tutorial will show you how to implement the combat system using only the Weapon Manager and the second one will implement the combat system using the Action Manager to help manage complex actions and action replication across the network.

If you are having any problems or have any questions about how the combat system works that seems obscure you can contact me in one of two methods.  The first is using the "Support" page to directly email Asadeus Studios Support and we will get back to you as promply as we can.

The second method also comes with access to the Combat System more detailed documentation on each individual System.

Go to Plugins
Fig 14.1 Go to Plugins

Go to "Edit" menu and select "Plugins".

Documentation
Fig 14.2 Documentation

Under "Asadeus Studios" category you should see the "Pro Networked Combat System" in your list.

Click on the "Documentaton" link to open up the online Google Doc that has a much greater detail of how each of the combat system's components work and what each function and variable does in these systems.

Most importantly in the "Additional Resources" Section of that documentation you will find a link to join the Asadeus Studios Discord Server.  Here you can directly chat with me and ask direct questions.  As a fair warning I am only a single developer and have contact obligations I must also take care that comes first so please have patients.


Print