PNMS Concepts

Introduction

This article is meant to get you started understanding some key concepts about the Pro Networked Mounting System and how it works so that you can better integrate it into  your games.  The system is built leveraging S.O.L.I.D. software design principles with an emphasis on Dependency Inversion to allow you to more easily integrate it into your game.

System Overview

Let us begin with a general overview of the system and what the various parts of it do as well as a very basic understanding to the steps required to add it to your game. 

In general mounting requires the coordination of 3 actors.  They are:

  • The Controller - this is either the Player Controller or the AI controller
  • The Rider - A Pawn or Character which is the normal character the player or AI controls
  • The Mount - The thing you want your Pawn / Character to be mounted onto.

Interfaces

  • IADMUnifiedControllerPawn - This interface is added on and is implemented on all three of the actors (Controller, Rider, Mount).
  • IRiderControllerInterface - this interface is added only to the Controller
  • IMountRiderInterface - This interface is added only to the Rider
  • IMountablePawnInterface - This interface is added only to the Mount
  • ILinkedMountActor - This interface is added to linked actors (turrets that Riders can control or have independent physics)
  • ILinkedMountActorOwner - This interface is added to Mounts who have linked actors.

Components

  • URiderControllerComponent - This component belongs on the Controller and communicates with the Mount and Rider through their interfaces
  • UMountRiderComponent - This components belongs on the Rider and communicates with the Controller and Mount through interfaces
  • UMountablePawnComponent - This component belongs on the Mount and communicates with the Controller and Rider through interfaces

Setup Overview

This section will provide a high level overview of what steps need to be done in order to integrate the PNMS into your game.  The Tutorials will guide you through it in more detail, providing the full steps to implement the various interface functions.

Controller

  1. Add the IADMUnifiedControllerPawn Interface to the Controller
  2. Add the IRiderControllerInterface to the Controller
  3. Add the URiderControllerComponent to the controller
  4. Implement the IADMUnifiedControllerPawn and IRiderControllerInterface using the URiderControllerComponent functions

Rider

  1. Add the IADMUnifiedControllerPawn interface to the Rider
  2. Add the IMountRiderInterface to the Rider
  3. Add the UMountRiderComponent to the Rider
  4. Implement the IADMUnifiedControllerPawn and the IMountRiderInterface using the UMountRiderComponent functions
  5. Setup the Rider's Animation Blueprint to have a seated animation.
  6. (optional) setup mounting, dismounting, and change seats animations
  7. (optional) setup move to position functionality

Mount

  1. Setup the seat sockets on the static or skeletal mesh of the mount.
  2. Add the IADMUnifiedControllerPawn interface to the Mount
  3. Add the IMountablePawnInterface to the Mount
  4. Add the UMountablePawnComponent to the mount
  5. (optional) add the IlinkedMountactorOwner interface to the mount
  6. Implement IADMUnifiedControllerPawn and IMountablePawnInterface using the UMountablePawnComponent functions.
  7. Define the seat properties on the UMountablePawnComponent

The Pawn

The pawn is an Unreal Engine class that is part of the Gameplay classes and is the base class that allows a controller to take possession and control it.  The Mounting system has the ability to mount any Actor in the game, but it is important to remember that only Pawns and Characters (which are child classes of Pawns) can be controlled by the player directly.

Controlled Pawn vs Owned Pawn

vs Mounted Actor

A Key concept to the PNMS is managing who and what the Controller is currently controlling.  The system introduces the concept of a "Controlled Pawn" and an "Owned Pawn".  The Owned Pawn is the players original character that they play when not mounted (the Rider).  The Controlled Pawn is the pawn the player is currently controlling.  During play the Controlled Pawn and Owned Pawn can be either the same or different.  The value of these can be retrieved from the URiderControllerComponent using the functions "GetOwnedPawn" and "GetControlledPawn".

  • If not mounted then the Controlled Pawn and the Owned Pawn will be the Rider
  • If mounted and controlling the mount then the Controlled Pawn will be the Mount and the Owned Pawn will be the Rider
  • If mounted and not controlling the mount then the Controlled Pawn and the Owned Pawn will both be the Rider.

In addition to the Controlled Pawn and Owned Pawn the system also tracks the Mount Actor separately.  If the Rider is mounted then the reference to the mount will be valid.

  • If not mounted then the Mount Actor will be invalid
  • If mounted and controlling the mount then the Controlled Pawn and the Mount Actor will both be the Mount
  • If mounted and not controlling the mount then the Mount Actor will be the Mount and the Controlled Pawn will be the Rider.

The relationships for owned and controlled pawns is setup on the controller using a function called "SetControlledPawn".  In general this function is called on the Controller event "On Possess".

On Possess
Fig 1.0 On Possess

The first time "SetControlledPawn" is called it checks to see if the own pawn is already setup, if it is not then the pawn passed in becomes both the Controlled pawn and the Owned Pawn.  When "SetControlledPawn" is executed again then it only sets the controlled pawn.

Override Pawns and Mount
Fig 2.0 Override Pawns and Mount

At any point you can override what the Owned Pawn or the Mount Actor actor is.  Calling "SetOwnedPawn" overrides any currently setup owned pawn the controller may have registered which is useful if you have a game where the player can switch to different characters.  Calling "Set Mount Actor" is available but not suggested to use because it only sets the mount but does not trigger any of the flows required to actually place the character onto the mount.

Positional vs Direct Mounting

The plugin supports two types of mounting.

Positional Mounting is used when the rider approaches the desired mount and is mounted to a seat based on the position they are relative to the mount.  For instance in the horse example when a rider is closer to the front left or right side of the horse they will always mount to the driver seat and either on the left side or the right side based on where they are standing.

Direct Mounting is used when the player is allowed to directly select what seat they want to mount to.  For instance you may have your rider approach the vehicle and interact with it.  Upon interaction a menu may appear giving them options to select a seat to directly mount to.

Linked Actors

Linked Actors are a concept within the PNMS that can be used to represent something like a turret.  They are Pawns that the player can take control over and operate independently of the driver.  Most often these will represent something like a gun turret you find on a space ship or a mounted gun on a truck.

Mounting Flow

Throughout the various tutorials and documents you will most likely see mention of the "Mounting Flow" or "Mounting Process".  This is a catch all for what features and steps you have decided to utilize as part of your mounting system for your game.  The PNMS system provides methods for you to customize how you want your character to approach, attach, and take control of a mount.

Simple Flow

The Simple flow is what the getting started tutorial will implement.

Simple Flow
Fig 3.0 Simple Flow

This flow features no moving into place and no animations playing to attach during the mounting process.  It simply snaps your character onto the mount and possesses it if needed.

Full Flow

The full flow is not covered in the getting started tutorials but is provided as supplementary tutorials you can follow along with to enable.

Full Flow
Fig 4.0 Full Flow

The full flow has the rider move into position upon interacting with the mount and then play animations to mount or dismount.  Optionally you can also play animations for transitioning between seats.

As an important note, the PNMS supports moving into place but provides no functions that actually perform moving into place.  The above gif shows a very rudimentary method of moving the player into place before mounting.

Mixed Flow

Additionally you can do a mixed flow where you can move the player into position or play animations for mounting and dismounting.  You are also not limited to using one particular method for your entire game, you can mix and match the flows you want to use based on the vehicle.

Deprecated Functions

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

Deprecated Functions
Fig 5.0 Deprecated Functions

The primary reason for deprecating a function is either to improve clarity on the purpose of that function or because the functionality that function represented is no longer needed.

Deprecation Stages

This section will outline the Deprecation stages.

Soft Deprecation

The First stage is a Soft Deprecation, the functions are simply placed within a deprecation category but all logic that calls them from within the components is not changed.  They will still be called by the components but their return values will be checked for invalid values and the replacement function will then be called instead.  For instance if you have a deprecated interface function that returns a boolean the system will look if the returned value is false, and if it is, it will then call the new function, but if it is true it will print a warning about the deprecation of that function and skip the new function. 

Hard Deprecation

The second stage is Hard Deprecation. All logic that originally called that function is removed and if there are newer functions they will completely take over.

When first deprecated the function is assigned a category of the format "Deprecated UE4.X". This indicates the unreal engine version where the Hard Deprecation will go into effect.  We still do not remove this functon from the interface because it gives developers one final chance to move their logic into the a new function which is almost always provided.

Removal

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

Deprecation Time Frame

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

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