Unreal Engine 4: Let’s Make: Interaction and Pickup System

Let’s Make: An Interaction and Pickup System. With it, the player is able to interact with objects around them with a simple button press.

Overview

An interaction system that allows the player to look toward a custom actor and use a simple button press to interact, pickup or use it. The blueprints are setup so they can easily be expanded upon later for other interaction types by using a parent actor and basing children off of it.

The current version will use:

  • Parent Interactable Actor
    • Class used to setup Child actors
  • Player Pawn uses Dot Product to find best interaction
  • Pickup actor
    • Attaches actor to Character’s Left and Right hands
    • Able to drop pickup on the ground below the character
  • Elevator & Lever Actor to show off multiple interaction types
  • Blueprint Only
  • Uses Unreal Engine 4.8.1

Player Character

We will use the basic character class and modify it to highlight the “best” interaction based on what we are looking at. The actor that is closest to the center of our screen will be chosen.

We also have functions for the button interactions like activating an actor or dropping an item within the character class.

Interaction Actors

The interaction actor will be created as a parent with children classes based off of it. This allows each individual subclass actor to have its own unique functionality without having to rewrite any of the basic code inherited from the parent.

If you are unfamiliar with creating blueprint child classes check out this documentation here: Child Classes Blueprint

The reason we want to use a parent class is two fold.

First, all the children classes we create based off of the parent will contain the same code but allow us to easily modify or remove certain parts of it as needed. Every interaction actor we make will need to be able to be highlighted and selected the same way so creating the code once for all interactions in our game makes this easy and clean.

What happens after the initial interaction will be different. One actor may act as a switch while another will be a pickup. Both will share the same UI elements and interaction code, but when activated, will do completely different things.

Using Child classes allows us to do this!

Second, all the children classes can be stored within the same parent variable. For example, we will be using an array variable within our player character so we can keep track of all the interactions that are around us. In order to do this we can use the variable type of the parent class but are free to add any of the children classes to it! This makes keeping track of the interactions easy and only requires a single variable while allowing us to access the parent functions within any of the other child actor types.

This means that no casting will be needed for each individual class and no Blueprint Interfaces either! All in all we could set this up using interfaces but we would lose out of reusing the parent class’s code.

Note: We do have an issue if any of our child classes have something specific to be called from within the character class. We store them in the parent variable type and lose out on anything within the child classes. This is normally fine as long as we plan accordingly.

Below are the children classes we will be creating based on the parent.

  1. Pickup Actor
    1. On Interaction – Player pickups the actor and releases it with another button
  2. Elevator Actor
    1. On Interaction – Elevator move from start to end locations
    2. Pressing the button again returns the elevator to the starting location
  3. Switch Actor
    1. On Interaction – Switch toggles from On to Off
    2. Once completed the switch uses Event Dispatchers to send out signals for its new state

Editor Functionality

The main thing we are attempting to accomplish with a setup like this is flexibility for the designer to create any type of object or interaction and have it work with the system easily with minimal change. Custom sizes of objects and location for each of the elements is key and we will support it when we create the parent Interaction class. Here is a quick overview on how it’ll work once we are done.

Interaction UI

This is a simple Blueprint Widget which acts as our UI Popup on top of our interaction actor. It lets the player know which is currently highlighted and gives a text description of what it does, like “Interact”, “Pickup”, “Turn On”, and much more. The text can be changed per child class or even within the editor for special cases.

Let’s get started

I have started off by creating a new project with the Third Person Template as my base. This will simply give us access to the third person blueprints and game modes right away but isn’t strictly needed. Feel free to augment an existing project or use another template that works for your game mode.

Create Blueprint Actors

Let’s create a new blueprint based off of the Actor Class. This will be our parent interactable class entitled, BP_InteractableActor. All the other children will be based off of this class allowing them to use the basic code we setup here.

Once we have created the Interactable Actor class we can right click and create the children classes.

ContentBrowser_CreateChild

Finally, we need a new Widget Blueprint located under the widget drop down section when creating a new asset in the content browser.

ContentBrowser_NewWidgetBlueprint

The content browser should be similar to the image below with our parent blueprint actor, three children actors based on the InteractableActor and our ThirdPersonCharacter and ThirdPersonGamemode which are added automatically when using the Third Person Template.ContentBrowser_Blueprints

If you are using a different game mode you may have a different character and game mode added in already. Really we just need to make sure we have the player character setup and ready to create the interactions.

Third Person Character

Double click on the Character Blueprint so we can setup the variables and functions we need for the interactions.

As much as possible I try and plan out the code I’ll need for a specific actor or action. I do this on paper (or whiteboard) and by creating empty functions and variables in the blueprint. Although I am not always right in my predictions, planning out ahead of time helps quite a bit and can save a lot of time. Adding in an extra function is easy and creating each function and variable while I go through the logic of what needs to happen makes sure I have an easier time staying on track once I begin coding.

Let’s add in the following functions:

  • Update Character
    • Simply a container for all other update functions
    • Add float input
      • I named it DeltaTime and ran the delta from the tick event to it
      • Within the function we update our DeltaTime Variable
  • Check Interactions
    • Checks to see if our array of actors has anything in it before doing a full check
    • If we are not near a Interaction Actor – Do nothing!
  • Get Best Interaction
    • Iterates through our list of actions and finds the one we are looking at
  • Set Current Interaction
    • Sets the best action to highlight it
    • If we have no interaction to highlight
      • If we pass this function nothing, it will set our interaction to null
    • Add a BP_InteractionActor as the input for this function
  • Attempt Interaction
    • If we have a highlighted actor – Attempt the interaction
  • Add Interaction
    • Add an interaction actor to our list
  • Remove Interaction
    • Remove an interaction actor from our list
ThirdPerson_Overview

Add in the following variables :

  • RightHandPickup
    • Variable Type: BP_Interactable_Pickup
    • Holds item currently picked up in right hand
  • LeftHandPickup
    • Variable Type: BP_Interactable_Pickup
    • Holds item currently picked up in left hand
  • RightPickupSocket
    • Variable Type: Name
    • Socket Name we will create in the character skeleton
    • Set as: “R_HandSocket”
  • LeftPickupSocket
    • Variable Type: Name
    • Socket Name we will create in the character skeleton
    • Set as: “L_HandSocket”
  • AvaliableInteractions
    • Variable Type: BP_InteractableActor
    • Set as Array: Create Blueprint Arrays
    • Holds all of the interaction actors close enough to the player
  • HighlightedInteraction
    • Variable Type: BP_InteractableActor
    • Holds the currently highlighted actor
    • When the player presses the interaction button this actor will be activated
  • InteractionDotThreshold
    • Variable Type: Float
    • Threshold that must pass when comparing the camera direction to the actor location
    • Set as: 0.85
  • DeltaTime
    • Variable Type: BP_InteractableActor
    • Holds our delta time from Tick event

Setup the Tick Event

Once we have created each function and variable we can string them together and setup each function’s code, starting by adding in the Tick Event and hooking it up to the Update Character function.

ThirdPerson_Update

This is really just a container for all the functions we might have for our update group, so it isn’t strictly needed. A normal collapsed graph might be fine or even just setting up the update functions right in the main event graph would work as well. I simply do this as a way to make sure all of our code is collapsed and easy to look through and easy to add to later.

For example, if we decide to add a large number of functions to the update code later it would be easier to just stick them in this container instead of letting them fill up the event graph. (Again, more a personal preference for organization and can be changed if desired)

Setup the Update Character function we just added as shown below. Again, if more code is needed we could easily add extra functions or code after our check interactions.ThirdPerson_UpdateCharacter

Now lets dive into our Check Interactions function and begin our interaction logic.

ThirdPerson_CheckInteractions

This function first makes sure we should check for interactions at all by asking if we have any actors near by. If we have no actors in our list we know we shouldn’t be highlighting anything and make sure this is the case by setting our Set Current Interaction function to none.

We will work on the Current Interaction later but for now leave it hooked up as shown.

Next we call Get Best Interaction to find the interaction we are looking at from our array. This is achieved by first getting the direction between our two locations, the UI element we interact with and the player camera. Next we normalize it, giving us only the direction and no magnitude. Finally we can use the dot product of resulting direction and the forward direction of the player camera to compare the two. The resulting float moves closer to 1.0 if both of the directions are the same.

In our case, if the direction from the camera location to UI location is the same as the camera’s forward vector, the player is looking directly at it.

ThirdPerson_GetBestInteraction

We loop through all of our interaction actors using the forloop node. This will grab each interaction in our list and add the resulting Dot product float to our local variable float array. We use this ActorDots array as a collection for all of our interactions and after its done, find the one closest to 1.0.

Unreal already has a nice function to find the max or minimum numbers in an array and we use it to get our best interaction. But before we send it to our Highlight Actor we need to test it against a threshold to make sure its in front of our player. My Threshold variable is set to 0.85 which makes sure we are looking toward it a good amount before having it highlighted. Feel free to play with this to your liking.

As long as our best interaction passes our threshold, we can send it to our next function, the Set Current Interaction. If not, then we set our Current Interaction to none as shown on the false branch.

Field Trip to the BP_InteractableActor

Before we can setup our Set Current Interaction function we need to create a function within our parent BP_InteractableActor class.

Lets open up the class and create a new function named ToggleHighlight with a boolean input labeled Highlight. We won’t go into detail on this function yet and keep it empty for the time being.

This function will simply hide or show the Interaction Actor’s UI but for now we just need to be able to call it from within the character class.

Returning to the BP_ThirdPersonCharacter

Lets jump back into our character class and into our Set Current Interaction. This function will set our Highlighted Interaction variable within the player as well as call the highlight function we just created on the selected interaction.

ThirdPerson_SetInteractionIgnore the “Pickup” comment in the top left, creating the correct comment was missed. This function doesn’t actually do anything other than highlight the currently selected interaction. Just shows and hides UI and stores it for later when we do interact or pickup the actor.

This function does the following:

  1. Check if our new interaction is null or not by using the IsValid node.
    1. If Null, we move to the bottom section of the function and deselect the previous interaction by setting the ToggleHighlight check box to false
    2. If a previous exists, deselect it before we set the interaction variable to null.
      1. Uses the Validated Get node (See below for details)
  2. Check if the new interaction is the same as the old by using a “Not Equal” node
    1. If they are equal, false in the branch node, do nothing
    2. This means we already have the same interaction highlighted and don’t need to do anything else
  3. Deselect the previous interaction if one exists
    1. If the variable is null move on
    2. If one exists ToggleHighlight and set to false
  4. Finally set the Highlighted Interaction to our input interaction and call the Toggle Highlighted function setting it to true

In this function I am using the Validated Get Node which has the ability to check if the variable is null or not. This is available as of Unreal 4.8. Right click on any Get node and select the Convert to Validated Get. It is just a nice way to save space but could be done using the normal IsValid nodes as well.

ConvertToValidated

Once we have this setup we are done with the Update functions! Lets go over everything we did so far!

  • Update function which finds out if we have any interactions near by
    • If we don’t have any set our Highlighted Interaction variable to null
    • If we have something to highlight move on to the Get Best Interaction
  • Get Best Interaction finds which actor we are most looking at and makes sure its within a threshold.
    • The threshold makes sure the interaction is near where we are looking.
  • Set the highlighted interaction
    • If we have a new interaction we make sure to set our previous interaction’s highlight to false before switching out the variable
    • Finish out by setting our new interaction to our Highlighted Variable and calling it’s highlight function set to true

Now that our update function is complete we need to add in two input keys for our character. These are the controls that we will want the player to use when they are interacting with our actors or dropping them on the ground.

ProjectSettings

This is done within the Project Settings menu and within the Input category. Add in both the Interact and the Drop input under the Action Mappings section. I have the interact set to “E” and the drop set to “R” but you can setup the keys or controller input how you like.

InputSettings

Once this is done we can add in our Input Events within the Character class so the player will be able to interact or pickup and object and then drop it later. We then hook them up to the two functions we made earlier, Attempt Interaction and Drop Item.

ThirdPerson_Interaction

Second Field Trip to the BP_InteractableActor

Again we need another function within the Interactable Actor before we can move on! In this case we need to create an Interaction Function. We again will leave it blank but this time we are not coming back to update it later.

Parent_Interaction

Our interaction function in the parent won’t really do anything at all!

In fact we want it this way because the parent class won’t ever be placed in the world. Its a base that all other actors get created from and thus it stays blank. Each child class will override this function to do something different when interacted but creating the function here allows all child actors to have this called.

Returning to the Third Person Character

Lets jump into Attempt Interaction within the character class. Below you can see that all we are trying to do every time the player presses the interact button is check to see if we have a highlighted actor and then calling the interaction function we just created.

ThirdPerson_AttemptInteraction

At this point we should be done with the character class except for the Drop Item function. We will be coming back to this but we want to setup the interaction actor and its children before hand.

Before we move on to the Interactable Actor lets setup the last three functions we need, the Add and Remove Interaction functions are first.

ThirdPerson_AddInteraction
ThirdPerson_RemoveInteraction

These are pretty straight forward, each contains an input with the BP_Interaction Actor type and simply adds or removes the passed interaction from our array. With both of these created we can move on to the Interactable Actor.

Finally we need to create the Pickup Item function which will be used for picking up and parenting the item to our character mesh. This will allow it to move with our animations based on the bone / socket we tell it to use.

Add in the function and set it up as shown below:

ThirdPerson_PickupItem

Note that I am using a local variable of Pickup which has our custom actor BP_Interactable_Pickup as its type. I do this simply to save space and keep the function more clean but isn’t needed.

We first set this local variable and check to see if it is valid before trying to add it to our character. Next we add it to the right hand if it isn’t already take. If it is we try the left hand and if both are taken we do nothing.

Each time we set our variable for each hand and attach it using the snap to location and using the socket we named in our variables. Later we will need to setup the sockets on our skeleton but for now its ok to leave be.

BP_InteractableActor

Lets start by adding in a few components to the blueprint we will need later. See the image below and add in the 4 components.

  1. Billboard Component
    1. Named: Icon
    2. The billboard is used as our root component so we have some control over the static mesh like relative location, rotation, and scale.
    3. Any image will do but I have kept the initial “dino” looking texture
  2. Widget Component
    1. Named: InteractionUI
    2. Our Widget component is set as our WBP_InteractUI class
    3. Set Space to Screen
    4. Set Size to X: 50 and Y: 75
  3. Sphere Collision Component
    1. Named: InteractionTrigger
    2. Used to see if the player is within range of the interaction or not
  4. Static Mesh Component
    1. Named: InteractionMesh
    2. Set to the default box mesh but any will do as we will allow each class to override the desired mesh for each object

Parent_OverviewLets take a look at the functions and variables we will need to create before we move on to the core code.

Parent_Functions

We have already created two of these functions, the Toggle Highlight and the Interact but I’ll go through the others quickly here.

  • Setup Interaction UI
    • Moves the UI’s location based on the UIOffset vector
  • Setup UI Text
    • Sets our UI Widget text so it can change based on the child actor needs
      • Some may read “Interact” while others read “Pickup”
      • All can be customized by class as well as in the editor for special cases
  • Toggle Highlight
    • Shows or hides the UI Widget
  • Setup Interaction Trigger
    • Moves the trigger based on the TriggerOffset variable
    • Changes the Sphere collision radius based on the TriggerRadius variable
  • Interact
    • Blank but is overridden in each child class
  • Setup Mesh
    • Sets the static mesh based on the ActorMesh variable
    • Moves the static mesh location based on the MeshOffset variable
    • Changes the static mesh scale based on the MeshScale variable

Lets setup the class variables next, making sure to make the ones that are public by pressing the eye next to it. We also want to check the Show 3D Widget for the locations so we can move them in the editor instead of just punching in numbers.

  • TriggerOffset
    • Type: Vector
    • Default (0,0,0)
    • Public
    • Show 3D Widget
  • TriggerRadius
    • Type: Float
    • Default 400.0
    • Public
  • UIOffset
    • Type: Vector
    • Default (0,0,50)
    • Public
    • Show 3D Widget
  • UIDescription
    • Type: Text
    • Default “Interact”
    • Public
  • Player
    • Type: Third Person Character
  • ActorMesh
    • Type: Static Mesh
    • Default Cube
    • Public
  • MeshOffset
    • Type: Vector
    • Default (0,0,0)
    • Public
    • Show 3D Widget
  • MeshScale
    • Type: Vector
    • Default(1,1,1)
    • Public

The first thing we need to do is setup the actor within the Construction Function. Here we can update the actor based on the variables we edit within the editor. This is setup so that each individual actor can be changed for special cases as well as the defaults within each child class.

Parent_Construction

We add in each setup function as shown. Once complete open each up and set them as shown below. Most are very similar and simply are moving our components in the local position, changing their scale, or changing their radius.

Setup Interaction UI just moves the UI Widget to our vector offset. Again this means we can update the UI location with a custom vector in the editor.

Parent_SetupUI

Setup Interaction Trigger moves the trigger origin to the offset and sets the sphere radius to our custom float. Again this allows us to easily change in the child classes and custom actors in the editor.Parent_SetupTrigger

Setup Mesh allows us to change the mesh used so we can switch it out in the editor as well as it’s location and scale.Parent_SetupMesh

Finally we need to set our UI Widget Text, however, we cannot do this in the construction script as the Widget doesn’t seem to be able to access the widget until the game begins and creates the actor.

Field Trip to WBP_InteractUI

In order to set the custom text we need to have a quick field trip to the WBP_InteractUI class. Lets open it up and create a new function called SetInteractionText with an input type of Text.

Widget_SetText_Basic

Leave this blank and we will return to it later once we work on our UI Widget.

Return to the BP_InteractableActor

So lets head back to our Interaction actor and set up the Begin Play event within the main event graph.

Parent_BeginPlay

Next lets add the code in to setup the text in our widget.Parent_SetupUIText

Note that in order to get the Widget component to use the correct class type we need to get the User Widget and cast it to our WBP_InteractionUI class.

Finally we need to tell our actor to be added or removed from the character array. Lets add in a two events from the Trigger component, one being the BeginOverlap and the second being the EndOverlap.

You can do this by right clicking on the InteractionTrigger and selecting each event. Once this is done lets add the code as shown below within the event graph.

Parent_Triggers

Each event first gets cast to our character, in my case its the Third Person Character. Next we set our player variable so we can use it later and within the children classes. Finally we use the character class to add and remove the actors from our list.

Once we have this setup we are done! Our Parent class, BP_InteractableActor can now be setup to use custom meshes as well as change the size of and location of the UI, Trigger and Mesh.

Lets move on to the first child of the Interaction class, the BP_Interactable_Pickup class.

BP_Interactable_Pickup

We will work on this class as it is one of the major features of the tutorial. In our version we are simply going to pickup the item and parent it to the character’s right or left hands and give the ability to drop them after.

Normally you may want to have a better UI for this, such as an inventory system or equipment selection which would allow the player to select with item to equip and to what hand as well as take care of dropping. However that is outside of the scope and this tutorial is quite long already! I may create another to show off a simple equipment UI piece at a later time and if others want to see how I would do it.

For our version we will simply add the initial pickup to the right hand and then the next to the left. When we try and drop one, we will first drop the left hand and then the right. Again, this is simplified for the sake of the tutorial so feel free to create a better system for how pickups should be handled.

Lets add in our default mesh for the pickup. You can keep it as the cube but I made a quick sword to show off the item pickup section. You can download the FBX file for it here:

Sword FBX file

We can change out the variables by accessing our Pickup class defaults which hold all the previous parent variables. Here we change what they are initially for all of our pickup actors, although we can also change them all in the editor individually.

Parent_Defaults

Feel free to change the static mesh out and what the text will say on our popup UI. After this we are ready to begin.

First lets open our Event Graph and override the Interact event by right clicking on the override functions drop down and selecting our Interact function. This will give us what looks like an event in the graph we can use.

Pickup_Override

Next we will right click on the Interact event and call the parent function. This isn’t strictly needed here because our parent function doesn’t do anything! But I wanted to show it off as well as put it in just in case we end up adding functionality to the parent and thus to all of our children.

Pickup_CallParent

If you are unfamiliar with overriding functions think of it as completely redoing how the function works within the specific class so when its called we completely ignore the parent code from the function and use our own which is placed here.

When we make a call to the parent function we are able to both create new functionality and reuse the previous code from the parent. This is important because when we might not want to have our child class ignore the parent function completely but instead add on to it. If we ignore it completely we lose out on code, if we had any, so this is the compromise of creating our own and simply calling the parent or in some programming cases its called the super.

The final overridden function will look like this:

Pickup_InteractNote again that we call the parent Interact Function but as its empty we don’t really need to if we don’t want to.

Next we turn collision off the actor, however you may not want to do this completely.

The pickup may need collision. A sword like ours may need it to be used in combat to see if it hit anything. However, because we have no attack animations I left it to simply turn off all collision instead of just the sphere collision for sake of time.

If you need the object to keep its collision feel free to change this out to only turn off the collision for the sphere trigger. We do this to make sure we don’t find it in our list of Interactions.

Finally we call the function Pickup Item from our player character we created earlier.

Before we leave our Pickup actor we need to setup the function to be called when we drop it. If you remember from earlier this is the last function we need to do in the character class as well. Lets add in the Drop function in this, the BP_Interactable_Pickup, class first and fill it out as shown below:

Pickup_DropWe begin by using the Line Trace node to find the position below the player, we use this to place our Pickup Actor on the ground. In this instance of the trace I am starting from the item location in the player’s hand and going straight down 2000 units to check for the ground.

Next we setup a branch to check if we actually found the ground or not. If we don’t find anything we move on, not dropping the item at all. If we do find a location we do the following.

  1. Reactivate the actors collision
  2. Detach it from the character
  3. Set its location to the position we found on the ground

Note that we are also returning a Boolean from this function so make sure to add in a Boolean output and name it Successful. This will be returned to the character where we call it and let us know if we were able to drop the item or not. If we fail we don’t update the character variables and keep the item attached.

Now that we are done with the Pickup Actor lets jump back to the Character class and add in that last function for dropping items.

Back to the Character Class

Lets open the Drop Item function and set it up as shown below. Notice that we call the function we just setup in the Pickup class and then branch the boolean output. Only if we are successful do we reset our variable and allow the character to pickup a new item.

ThirdPerson_AttemptDropAt this point the pickup interaction should work! But something is wrong as we don’t see the nice UI popup. We have yet to create it! So lets get to it.

WBP_InteractUI

Within our widget blueprint we need to setup the image we want to use and the Text function we created earlier. Add in the following widget components to our canvas and set them to the upper left of the screen.

  1. Vertical Box
  2. Image
  3. Text

Widget_Overview_CWe parent the Image and Text in the Vertical box by click and dragging them onto the vertical box in the Hierarchy. We can also change the vertical box to “Size to Content” so it will expand when needed.

I wont go into too much detail on how to create the UI systems so if you need help with this part be sure to check out the documentation here:

Widget Blueprint

Notice that I am using an image I created to show the interact key as “E”. Feel free to use it or create your own. I’ve uploaded my image file here:

Button UI

Make sure you change the image size to 50×50 within the widget details panel when you select the image. This changes our image within the Widget so it’ll fit better in our scene. You can play with these settings and change the size in the BP_InteractableActor and to find something that works for you.

Finally, set the default text to “Interact”, change the text size to 10, and make sure it is set as a variable by checking the box at the top of the details panel. This should take care of all our widget components and we can move on.

The last thing we need to do before we are done with this blueprint is setup our Set Interaction Text Function. We set this up earlier but need to complete it by adding in a set Text node.

Widget_SetText_FinalNow our text will update from our BP_InteractableActor to whatever we set it as in the variable.

Character Skeleton

Before the parenting will work we need to add the sockets on our skeleton so we have a spot to attach the items. Open up the character skeleton and add a socket to both the right and left hand bones.

In the details panel we need to set each socket to our variables names. The right hand will be “R_HandSocket” while the left is “L_HandSocket”. You will also need to rotate them into place making sure the forward vector sticks out the direction we need the sword to face.

Character_SocketName

At this point we should have everything we need in order to test out the pickup. You can also place the parent interaction actor but nothing will happen when we press “E” next to it. Go ahead and add a few actors in to make sure its all working.

BP_InteractableElevator

The elevator is a nice example of creating a very basic interaction which can be built off of the parent class with minimal change. Really we are just going to be adding a few things to get it working. Lets take a look at the viewport and setup a few things.

Lets begin by adding in a few extra variables we will need.

  1. Elevator Start
    1. Type: Vector
    2. Default (0,0,0)
  2. Elevator End
    1. Type: Vector
    2. Default(0,0,400)
    3. Public
    4. Show 3D Widget
  3. Play Rate
    1. Type: Float
    2. Default 1.0
    3. Public

Notice that we are not allowing the Elevator Start to be public. Instead we are having it fill in the variable from the initial location of the elevator.

Elevator_OverviewNext we select the Default properties at the top of the editor and setup all of our parent’s variables. For us we are making the cube larger and flatter by setting it’s scale to (8,8,0.25) and we can also change the UIDescription if you would like. I have mine set to say “Elevator”.

You may notice that all of our parent’s variables are missing on the left. We still have access to them, but we need to use the defaults to set them initially and right click and call them in the graph instead of dragging them out.

Now we can do two things to get this elevator moving, one is overriding the BeginPlay event. Lets add the event in and make a call to the parent event by right clicking on it and selecting Call to Parent Function.

We want to make sure we call the parent or we won’t have the Begin Play event call back to our parent. In this case we use this to setup our UI text function. If we don’t do that here we lose out on that code and our UI doesn’t update to our new text we give it.

Before we can continue we need to create a new Timeline to control our elevator movement. Right click in the graph and scroll to the bottom, adding in a new Timeline. Call it Elevator Movement.

Elevator_AddTimeline

Now we can setup our Begin Play event as shown below. We get our Timeline as a variable and set its play rate to our float variable. This will allow us to change how quickly it moves from point A to point B. The Elevator Start variable is also setup here with our initial location. (We could have also not created a variable at all for it and just used the Mesh Offset)Elevator_BeginPlayNext we need to make the elevator move!

We will be using the Interact function, overridden to make it move by using our timeline. Go a head and override the Interact and we will be ready to create our functionality.

Here I have opted to not call the parent, this would mean that if the parent adds code to the interact function we wouldn’t see it happen with the elevator. It would ignore it completely and move on to it’s own code show below. Feel free to make the call to the parent if you would like.

Elevator_Interact

Next we are using the Flipflop node to switch between the Play and Reverse inputs on the timeline. Each time the player presses the interact button we will either play forward or reverse the elevator back to the starting location.

Coming out of the Update output we have 3 different set relative locations. Each one is hooked up to the Vector Lerp which sets the location between the start and end locations.

Both the UI and the trigger locations are added to their initial offset so we never lose the initial location they start from. Instead we simply add to it to move in the same motion as the static mesh.

For those who do not know how the Lerp works, we are simply outputting a location between the two input vectors, the A and B. We base the output on the alpha float which moves from 0 to 1, or 0% to 100%.

  • If the alpha is at 0, it will output A.
  • If the alpha is at 1 or 100%, it will output B.
  • Anywhere in between will be output as well. For example:
    • If the alpha is at 0.5, or 50%, the location will be exactly halfway between Vector A and B.
    • If the alpha is at 0.75, the location will be 3/4 of the way from A to B.

By slowly moving the alpha from 0 to 1 over time we create the Elevator Movement.

But before we can hook this up completely we need the Alpha. Double click on the timeline to open it up and we can setup the Alpha.

Elevator_TimelineAdd in a float by selecting the F+ at the top of the curve editor. We can rename it to something descriptive, like Alpha. Next we shift click on the red line to create two points. Move one to the start at 0,0 and the next at 1,1.

Next setup the Length at the top to read 1 second long so the timeline ends at the correct time.

I also like to create a small ease in and out curve to it by right clicking on the points and setting them to auto. This gives us access to the blue tangents so we can change the curve as we desire.

When we change the float PlayRate we are changing how long it takes the elevator to move based on one second. If we set it to 0.5 we slow down how long it takes where as setting it to 2 will be twice as fast.

We now should have a working elevator! Drop in the blueprint actor and move the end location where ever you want it to move and setup the rate as desired.

We also may want to setup the elevator to only work once its movement is completed but for now it works well enough.

BP_Interactable_Lever

This lever is very similar to the elevator so I will post the code and leave out a lot explanation unless its needed later.

I use the cube again but you can change out the mesh to one that will work better as a lever.  I also have two rotation variables setup to -45 degrees on the pitch and positive 45 degrees. This will drive the movement I setup with the timeline.

Lever_Defaults

I also update the construction script to change our rotation as well. We have not needed it until now so I placed it within the child actor although we can add it to the parent if needed.

Lever_Construct

Finally we drive the lever movement with a Timeline and a Rotational Lerp. I also have Event Dispatcher created at the end of the timeline so we can call extra things to occur from the level blueprint when the lever is flipped on and off.

Lever_Movement

You can check out more about Event Dispatchers here in the documentation:

Event Dispatchers

Review

After all is said and done we should have a nice system for player interaction.

At this time it is quite basic and only works based on the camera view.

  1. The player looks toward the item they want to interact with
  2. The item highlights based on the best interaction
  3. Using the interact button, the actor begins the interaction code
  4. Code can easily be changed by creating child actors based on the parent

Some games like The Witcher 3, create a similar mechanic for selecting and picking up items. However they base the highlighted interaction on the main character’s direction. We can do this as well and simply need to add in a check against the character’s forward vector as well as the camera, combining the two into a similar mechanic.

I do have some issues with this system as it focuses on the character’s forward vector. The player may have trouble selecting an item if they need to re-position themselves to be looking at it. Specifically items that are right at the character’s feet can be difficult to highlight, requiring them to move away and turn around to face it before they can select it. This can be difficult at times and I tend to opt to an easier system by just using the camera rather than focusing on the realism of the character facing what they are interacting with.

You can always have the character turn to face the interaction automatically afterward.

This code is quite long and I haven’t had a chance to really look through it and make sure its all good to go! Feel free to let me know if I missed something in the tutorial or if some of the code would work better created in a different way!

For now that’s it and hopefully it helps people get started on creating their own interaction systems!

Cheers!


EDIT: I’ve updated the tutorial a bit to help make a few things more clear. A main issue found was the Variables in the character named RightHandPickup and LeftHandPickup should be set as the BP_Interactable_Pickup type. Previously, they were written out as the parent actor type which means that you cannot call the functions we wrote for them in the pickup child class! This is fixed by changing the type to the correct child type and has been updated in the tutorial.

This was found by Damon so special thanks for catching it and helping clear it up!

Categories: Tutorials | Unreal Projects

21 Responses to “Unreal Engine 4: Let’s Make: Interaction and Pickup System”

  1. After setting up the functions and variable you initially told us to set up, new ones seemed to come out of the blue further on in the tutorial. ‘Actor Dots’ and ‘Interaction UI’ are a couple examples. So, now, I feel stuck and can’t proceed further into the tutorial… Should I just re-read this or did you accidentally leave some things out?

    • Hey Damon, sorry to hear that! I might have missed a few things so thanks for pointing them out! I’ll go through the tutorial and see if I can clear them up. For the time being I’ll see if I can help you out here.

      The Actor Dots is a local float variable that I set to be an array. While inside a function, you can add a local variable, located below the normal variables. The main difference is that this variable doesn’t exist outside of our function and will reset each time the function is called. We just use it here to keep track of our dot values so we can compare them after the foreach loop is complete! In our case this is apart of our character and inside the “Get Best Interaction” function. Just add the Actor Dots in as a local variable, set as array, and connect it as shown in the picture shown here:

      http://gregmladucky.com/blog/wp-content/uploads/2015/07/ThirdPerson_GetBestInteraction.png

      The Interaction UI is the Widget Component that is added to our BP_Interactable Class. I named mine InteractionUI but I think I have failed to state the name in text. You can see how its setup here in the image with the InteractionUI named:

      http://gregmladucky.com/blog/wp-content/uploads/2015/07/Parent_Overview.png

      I used a widget component as it made placement above the items much easier. This is opposed to creating the widget on the player screen and aligning it to the in world object each frame.

      Hopefully that will get you going for now and I’ll see if I can update the tutorial to read better! Feel free to ask any other questions in the mean time!

      • Hi Greg,

        I’m currently pursuing my career in independent game development, and am still fairly new to both Ue4 and coding (visual/nonvisual) in general. You’ve been an awesome help along the way! I can see many many uses for this in my game in the context of this tutorial and even more based on what I’ve learnt from it – that’s my super long way of saying, thank you sir!

        I’ve almost completed the tutorial I so I don’t actually think there’s anything you really need to add. I just needed to learn about local variables.

        I did say almost! Sorry, I got a little stuck again – just a small issue near the end, http://gregmladucky.com/blog/wp-content/uploads/2015/07/ThirdPerson_AttemptDrop.png

        My Left Hand Pickup node won’t connect with the Drop Item Function. Apparently it’s because the Left Hand node (and Right Hand) is a reference to the interactable actor BP, and the function target is reference to the interactable pickup BP.

        Any idea of how I should handle this? I think it’s probably a simple fix!
        Again thank you so much, this tutorial and blog are incredibly valuable and in depth, I’m sure many people like myself have learned a lot.

        • Hey Damon, it sounds like you just need to change the variable type to the child class. You can do this by selecting it and changing the type drop down to our child pickup, the BP_InteractablePickup class.

          I believe I might have that wrong in the tutorial! I’ll check the blueprint and change it out! Thanks for the find!

          When you do that it will most likely delete some connections in the blueprint graphs so you will need to go through and reconnect the connections that broke.

          Hopefully that helps!

  2. Hi Greg,

    thanks for making this tutorial. I’m a noob at this so maybe I just didn’t get something but I think you forgot to write how to actually toggle the highlight. At least my InteractionUI is showing at all times.

    • And another question: If my hands are full and I attempt to pick up another object, the object stays on the ground but the interaction with said object is removed (and doesn’t come back). Did I make a mistake in the Blueprint or is is the same for you?

      • It’s not you, it’s a mistake in the tutorial. What happens is that the collision for the InteractablePickup is disabled regardless as to whether the item is actually taken or not. Here’s an unofficial errata:

        In the interact event for BP_InteractablePickup, change the following:

        1) PickUpItem should be the first node called after Parent:Interact.
        2) Add a boolean output variable to PickUpItem. Return it after each AttachActorAsComponent node.
        3) Add a new Branch node to be called after PickUpItem. If the new boolean output variable is true, call SetActorEnableCollision node. Otherwise, do nothing!
        4) Test your code. You should now be able to pick up two items and only two items. Attempting to pick up three items will not work, but the collision will remain and you’ll be able to pick it up after dropping an item.

        As for your first question, here’s how to set up highlighting:

        1) Go to your InteractableActor, open the ToggleHighlight function. If you were following along with the tutorial, it is blank.
        2) Drag the InteractionUI down as a Get. From the Get, place a new “Set Visibility” node.
        3) Pipe the Highlight boolean from the start of the function onto the New Visibility boolean.
        4) Open up the properties of the InteractionUI. Find the “Visible” property and uncheck it.
        5) Test! The InteractionUI should default to invisible, until you walk into its range. Once in range, the InteractionUI should become visible. If you leave range, the InteractionUI should be invisible again.

        • Thanks Eevi!

          Yes, it looks like the current blueprint script has the issue where it should not turn off collision but is setup wrong. Above should fix the issue and I’ll see if I can update it in the tutorial to reflect that.

          It also does look like I’m missing the Toggle Hidden Function here! (Again thank you Eevi!) You just need to set up the toggle function to use the Set Hidden in Game or Set Visibility node as described above. I’ll add that in as well.

        • Thanks for your help Eevi. Seems to work, but if I add a Bolean as output for PickUpItem isn’t it always true if I picked up the item at least once? So if I try to pick up an item that I picked up and dropped before, while having full hands, collision gets disabled.

  3. hey Greg I would like to change my question… I solved that about moving the elevator with a lever using a custom event and a get class (it was easy) now the question might be…in the elevator ¿what makes the character stick on the platform?

    cheers!
    nice tut still chewing it

  4. Hi Greg,

    In following this tutorial I am having a hard time with the InteractiveUI section. You have a widget up at the top…
    Named: InteractionUI
    Then down below you have a variable with the same name, with a solid blue circle icon. What variable type is that? I also get an error when trying to have them both with the same name.
    I renamed the widget for troubleshooting and if I change the varible InteractionUI to type: WBP_InteractUI it makes the circle hollow.

    Help, confused!

    Ash

  5. Hey, thanks for sharing.

    How would you go about implementing multiple actions per object, and being able to call them dynamically (for instance, each interactable declaring which actions it supports)?

    I was thinking of having a string array in the base interactable that child classes extend with the actions they support (say BP_Pickup supports being picked up, but BP_Sword (derives from BP_Pickup) supports both being picked up, and also hitting someone (or another action)). My only problem is then, how to call those actions by string?

    Thanks in advance,
    Pedro

  6. It is Mar 2020 nearly five years after your original post. I am using 4.24 and I cannot get it to work at all. To begin, I placed a Print String for debugging into Attempt Interaction. I placed it into the “Not Valid” pin on the Get node. Whenever I try to pick up and item or use the elevator, I get the Print String message. This means that the HighlightedInteraction variable is not getting any values at all. Please advise, without a response, I will assume that this tutorial is meant for older versions of Unreal from 2015 and not the latest and will have no choice but to scrap the entire system and try to build one from scratch.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.