Interaction System

This asset includes a simple interaction system intended to help you get started with the interactables. Interactables are the things our player can use or pick up. This includes item pickups, containers, banks, vendors, and crafting workstations.

This implementation was created to be intentionally simple to make it easier on you to expand on or to replace with your own custom or third party interactable system.

Configure the Interaction System

You can configure the interaction system on the AC_InventorySystem component you added to the player controller. Select this component and navigate to the Configuration / Interact section using the details panel. These are all the variables that get used by the interaction system component that gets added to the player controller.

A description for each variable can be found in the Setup Guide.

How the Interaction System Works

It all starts from the AC_InventorySystem component we added to the player controller.

Select this component then using the details panel browse to the Configuration / Interaction category to see all of our Interaction System related variables.

One of these variables is called enableInteractionSystem? which when true (and is true by default) will let the AC_InventorySystem setup process spawn the AC_Inventory_Interaction component found in our Blueprints/Components/Systems/ folder and attach it to our Player Controller.

This AC_Inventory_Interaction component is where the keybindings, scanning, and interacting takes place. It is also responsible for attaching our UI_Interact_Notice (found in the UIs/Interact/ folder) when an interactable is detected near the player’s pawn. This widget binds into an event dispatcher on the component that calls when an interactable actor is detected, or no longer detected, nearby.

An Interactable actor in this system is an actor that the player must travel to to perform the actor's specific interaction event such as picking up an item, or opening a container. An interactable actor is defined by implementing the BPI_InventorySystem_Interactable blueprint interface. When the interaction component’s scan function runs, it is looking for nearby actors with this blueprint interface.

This interfaces has 3 methods, all related to the interaction process, here is what they are:

getInteractInfo This function gives us the opportunity to return the availability of the interactable, and a text label that defines the interaction (Pickup Item, Open Container, etc) which is shown on the UI_Interact_Notice.
interactWith Called when the player controller initiates an interaction event with this actor.
interactAnimations Also called when the player interacts with the actor. Used as an opportunity to play an animation on the interactable actor and/or the player pawn.

In this system each interactable is a child of the BP_Interactable abstract blueprint class. This class implements our blueprint interface and has a few helper functions to help with responding to the BPI functions. This includes a playAnimation default function which you can override to play a custom animation in your interactable. It also includes an overridable function called onInteract, which you can use as an alternative to overwriting the interactWith event directly. This is simply to offer a cleaner and more manageable approach with only one entrance for the actual interaction event implemented by our interface and base interactable class.

When the player approaches an interactable actor the Scan method in the component detects the actor with the blueprint interface, and calls the getInteractInfo method on it. The actor then responds to the component providing the state of the availability of that actor, and the interaction label. This information is then sent from the component to the client and the UI_Interact_Notice is shown with the interaction label.

This notice prompts the player to press our key binding defined in our IMC_InventorySystemV4_Interact in the Blueprints/Input/Shared/ folder.

When the player presses the interaction key binding it initiates the input action event on the interaction component event graph, which calls its interaction handler method using the last actor found by its scan method (if the actor is valid).

If valid, this interact handler method will call the interactWith blueprint interface event on that actor. When our actor receives the call to interactWith it performs an action specific to that actor.

For example if we are an item pickup like our BP_Interactable_ItemPickup the item is added to the player inventory and the actor is destroyed. Take a look at the pickupItem function in the BP_Interactable_ItemPickup to see how this works.

Another example would be if we are a container, the user is checked in as the owner of the container and the user interface for the container is shown to that player. Take a look at the onInteract override function in the BP_Interactable_Container.

This is the general flow of how interactables work in this system. There is a bit more going on with the containers and if you would like to learn more about that make sure to review the Container chapter.

Creating a new Interactable

Follow these steps to create a new interactable using everything included in this system:

  1. Navigate to the Blueprints/Interactables/ folder and make a child of either the BP_Interactable blueprint, or one of the other base classes you would like to inherit the functionality of. For example, if you are making a type of container or workstation you would use the BP_Interactable_Container or BP_Interactable_Workstation. You would only use the BP_Interactable base class if it is something completely new and you want to start from scratch.
  2. Override the getInteractInfo function, respond with your interaction label, and Available? with the state of the interactable. In most cases you will just respond true, but perhaps you want a way to conditionally control the availability. For example if you want an item pickup that can only be picked up at night, you would respond to the Available? variable with the result based on what your Time System says the time of day is.
  3. Override the onInteract function. This is the start of where you will provide your interaction functionality. A reference to the Player Controller performing this interaction is provided as an input on this function, and from it you can perform player specific actions.

Creating a new Interactable without using the base class

If you would like the included interaction system to interact with a custom interactable and you are not using a child of the BP_Interactable blueprint you will need to add the BPI_InventorySystem_Interactable blueprint interface to your actor and then implement the functions and events into your custom blueprint. The purpose of each of these methods is defined above in the How it Works section.

For multiplayer games you will also need to make sure your custom blueprint is also properly replicating.

Creating a new custom Item Pickup Interactable

In addition to the steps to create an interactable above you will also want to implement the BPI_ItemPickup blueprint interface. This interface adds two methods:

isPickupItem? The interaction system scan treats pickup items differently to support the pickup all input action. If you are creating a custom item pickup you will want to make sure your respond with true from this method.
setPickupItem This event is called when the player drops an item, it will include the relevant specifics, like quantity and dynamic data.

In addition to these methods you will also want to set your custom drop item handler for the item in the DT_Items data table. This custom drop handler can be set to your custom item pickup so when the player drops the item your blueprint is used instead of the default.

You can learn more about custom item pickups in the Spawn Items chapter.

Interaction Animations

The BPI_InventorySystem_Interactable includes the interactAnimations event.

The BP_Interactable base handles receiving this call for the interaction and relays to the player’s pawn to play a montage. This is handled using the BPI_InteractPawn blueprint interface, which contains the playInteractAnimation event. This event has an input called InteractAnimation which relates to the types of interactions the system supports by default. This method is called on your pawn when you interact, pickup a single item, or pickup multiple items. The interact and pickup ones are called through the BP_Interactable and BP_Interactable_ItemPickup playAnimation method. The pickup all is called from the AC_Inventory_Interaction component’s pickupAll method.

The AC_Inventory_Interaction component is what initiates these calls either directly through the interactable actor for interactions, and to the player's pawn directly for the “pick up all” animation. This call to the interactable actor for interaction is so you can specify per-interactable animations. This can be an animation you play for the interactable actor, or it can be used to relay a notice to the pawn to play a specific interaction animation, like the included item pickup blueprint.

If you need additional pawn interactable animations for your custom interactables you can extend the E_InteractAnimations enum in the Blueprints/Variables/Enums/ folder then override the playAnimation method in your custom interactable inheriting from the BP_Interactable, or if using a custom blueprint, in response to the interactAnimations event.

To use this on your pawn you need to add the BPI_InteractPawn to your pawn, then from this event play your montage. For multiplayer games you will want to call an event which is multicast to play your animation. Take a look at the included example on the demo character.

While this demo includes just one animation montage to play for all three, you can use this event to play different ones for each. The demo character while only playing one unique animation, it is set up to show you how to play multiple. The same value is set for each is the key difference.

Switching to a Line Trace

To use the included system but to change it to a line trace you will want to update the scan function found inside the AC_Inventory_Interaction component. The first execution path from the sequence near the start of this function is where the default sphere overlap occurs (look at the comments, it is labeled). The debug toggle is also in this location. You will want to replace these with your own line trace logic instead.

Nearby Interactable Notice UI

We explain how the nearby interactable UI works in the How it Works section above, but for reference the widget UI_Interact_Notice can be found in the UIs/Interact/ folder. This UI is listening to the client side event dispatcher onCurrentInteractableChangeUI found in our AC_Inventory_Interaction component.

When this event dispatcher is called a reference to the actor is included. If this reference is valid that means there is something to interact with, and the notice is shown. When this actor reference is empty then there is nothing nearby anymore and the notice should be hidden.

If you are going to make your own custom interaction widget these are the parts of this one you will want to look at. It all basically runs from this event dispatcher, the rest of the code has to do with showing the right key binding, and handling showing the different prompts if there are multiple item pickups nearby.

It is worth noting that this event dispatcher is only called when a change occurs. It will not call for each ping of the scan. If for some reason your code is missing this call you can check the existence of a value in the currentInteractable variable found in the AC_Inventory_Interaction component.

Interaction Input Actions & Event

The IMC_InventoryV4_Interact input mapping context can be found in the Blueprints/Inputs/Shared/ folder. This input mapping context is added by the AC_Inventory_interaction component on setup. It includes two input actions:

IA_InventorySystem_Interact - The single, default interaction event.

IA_InventorySystem_PickupAll - The pickup all nearby items interaction event.

The events for these input actions can be found in the event graph of the AC_Inventory_Interaction component.

Enable Hold to Interact or Pickup All

If you would like the interact or pickup events to require a hold time before activating it you can set that up by adding the Hold Input Trigger inside the IMC (mentioned above) for the input action. By default you would replace the Tap trigger with Hold, then set your HoldTimeThreshold to the number of seconds to hold for.

Since the purpose of this asset is not to offer a full fledged interaction system I left it at this point as it was the simplest approach. If you wanted to have different hold times for different interactables you would need to change the current logic to instead use and pass this threshold from the interactable actor instead.

Disabling the included Interaction System

It is very easy to disable the included interaction system, on the AC_InventorySystem component you added to the player controller just set the enableInteractionSystem? boolean to false in the Interact Configuration section. This will tell the inventory system not to add the interaction system’s component.

Using another Interaction System with the existing Interactables

In this scenario you will want to disable the included interaction system (mentioned above), and then set up the BP_Interactable to use your custom interaction system’s BPI. From your custom method you would call the onInteract override function that already exists in the BP_Interactable base class.

The one requirement is that you have easy access to the player controller making the interaction. For single player games you don’t need to pass this through, but for multiplayer it should be an input on your custom interaction event. We need the reference to the player controller to give items on pickups, and to show the UIs related to different interactables.