Interaction System
UE5 Inventory and Item System Version: 3.0This page will help break down the interaction system that is included with this system. This information can be helpful if you need to add onto it, or replace it with your own.
How it Works
Inside our AC_InventoryItemSystem component we are calling DoInteractPing every second, this is what scans for nearby interactables, and if one is found we will show the widget to Press E on the player's screen. Inside this function we do two thingsā¦ if we have a current interactable (like looking in a storage container) we check the current interactables distance from our pawn, and if it is greater than a certain threshold we force close the interactable. The other thing this doInteractPing is doing is checking for nearby interactables, and if found it shows the widget to interact with it. It does this using the ScanNearby function.
The ScanNearby function is a simple SphereOverlapActors that has a class filter of our BP_Interactable base blueprint. We then check each hit actor to see if it implements our BPI_Interactable interface. By default it always should implement it since by default we are using the BP_Interactable class filter which implements it. If you were to remove this class filter (which you might if you want to make your own interactable blueprint that is unhinged from my BP_Interactable base), then this BPI check will then come into use. The first interactable this scan nearby function finds is the one it will use and notify the player about, however this function will also tally up all the valid interactables items that can be picked up nearby and provide this count as well. This count is used to change the display, if there are multiple items that can be picked up the display will say press F to pickup all instead.
At this point our player can either press E to pickup one item, or interact with a non-pickup item. Or press F to pick up all nearby items if multiple are found. These keybindings are driven by the Enhanced Input System, and you can change the keybindings in the IMC_InventoryItemSystem found in the Blueprints/Input/ folder. IA_InteractClosestNearby is the E key by default, and IA_InteractPickupEverything is the F key. The execution of these events takes place in the AC_InventoryItemSystem's Key Bindings event graph. Both of these events can be found next to each other in the "Interact System" commented section.
The pickup everything event is pretty straightforward, and will just attempt to pickup everything nearby, if this feature is enabled. The function it calls we get all nearby interactable items and call the interact event on each one (for pickup items the interact event is what adds it to the player inventory and removes it from the world).
The interactevent does a few things, and what it does depends on our state and what is nearby.
First it will check to see if we have an intractable window already open, and if we do when we press our interact key, it will then close the window.
If we don't have an intractable open it will then check to see if we have the "hold" to pickup option enabled, which is an alternative to the pickup everything nearby event. With this feature enabled and while holding down the interact key our player will pickup a nearby item every 0.3 seconds.
If the hold to pickup option is not enabled we will just fire off our InteractNearby function once.
The interact nearby function will call our ScanNearby function to get our closest interactable, if one is found it will call the interact function on the interactable, which comes from our interactable blueprint interface which is also implemented on our interactable. The interaction event will always be called at this point, but if the interactable object is not equal to our current interactable we then check to see if the new interactables type is a match for our current type, if it is we just continue through the process. If the new interactables type is not a match for our current interactable and our current interactable is valid, we then force close the window if it is still open. This comes in handy if your player has multiple interactables that are nearby and is cycling between them.
What happens at this point depends on the interactable, and to see what each interactable actually does open up the blueprint for it and take a look at the Interact event. For storage containers, or NPCs this will show the UI. For pickup items this will pick up the item.
Create a new interactable blueprint using this system
To add on to this logic and create your own type of interactable you just need to make a child of the BP_Interactable found in the Blueprints/Interactables/ folder. Then override the Action event which is what is called when the player interacts with your interactable. The BP_Interactable also provides you with 3 variables, the interactable name, action and type. These variables are used to inform my interaction system with the data it needs when showing the widget on screen, as well as handling the type of interaction it is within the functions mentioned in the How it works section. Go ahead and fill out the data you would like to use in these variables, and to add a new type to the enum E_InteractableTypes found in the Blueprints/Variables/Enums/ folder. Take caution when editing enums. If you remove something from this list you may end up creating a hole in the code. I also recommend avoiding re-arranging this list. The only thing you should do here is add a new enumerator to the list if you need.
Create a new interactable blueprint using this system without using BP_Interactable
Under most circumstances you should be able to just make a child of BP_Interactable when you want to make a new interactable blueprint. However you may come to a crossroads where you need to create your own compatible interactable without using my BP_Interactable base.
First create your new blueprint actor, then add the BPI_Interactable blueprint interface to it.
Implement the Interact event and getInteractableInfo functions that were added to your blueprint when you added the BPI_Interactable blueprint interface. Remember the interact event is what you want to happen when your blueprint is interacted with. For your first test keep it simple and have it just do a print string. The getInteractableInfo is what is used to get some simple information about your interactable, you will want to at least provide the InteractableAction as this is the word that is shown on the widget that pops up.
The last thing you need to do is a one time change, inside the AC_InventoryItemSystem's ScanNearby function we need to remove the Actor Class Filter from our Sphere Overlap Actors. By default this Actor Class Filter is using our BP_Interactable, so it won't ever detect your new unhinged blueprint. Simply set this to none, compile and save.
You should now be able to drop your new blueprint in your level, and when you get close enough to it you should see the widget to interact with it, and when you do you should see your print string appear.
Using your own interaction system alongside the included system
If you would like to maintain all the features and functionality included with the interaction system provided within this asset while also having your own interaction system work alongside it you would just need to combine what happens in my key binding (on the Key Bindings event graph inside the AC_InventoryItemSystem) with what happens in yours. Basically you would always run your code first, and only if your code didn't do something you would then run mine. There are a few things going on with this event at my end as I described in the How it Works section. If you want to keep all the features, convert the Started & Completed pins coming out of the IA_InteractClosestNearby input action to new custom events, this will make it easier to work with at your end. After creating these new events you can then delete the EnhancedInputAction IA_InteractClosestNearby, since it is no longer needed.
Now let's head back to your own interaction system's input action. After yours finishes whatever it is doing, and only if yours didn't find something should you continue with calling the one on my system. For example, everything that happens on yours could be inside a function that returns a boolean with a value of true if it found something or false if it didn't. We could plug this boolean into a branch and from the false execution path then call our interact event we created when we converted the event in my system.
At this point you should be able to go ahead and hookup both of the events you created in my system to the execution paths in yours. Make sure to do the Completed/Released event as well if you are adapting the full functionality.
To get a reference to the AC_InventoryItemSystem first get a reference to your Player Controller, then from it drag off and select Get Component by Class. In the class list select AC_InventoryItemSystem. You can then call the custom events you created in the AC_InventoryItemSystem's Key Bindings event graph from this Get Component By Class output pin. Since this is the kind of thing that will be called pretty often it might be a good idea to cache this reference somewhere at your side on begin play instead of calling the component by class every time. The choice is yours, I am just a little picky about something like that.
Replacing the included interaction system completely
Under most circumstances you should try to work alongside my interaction system using the instructions above. However if working alongside my system is not an option and you need to completely replace it with your own then you need to be prepared to do some surgery. You also need to keep in mind this interaction system has been integrated throughout all the other major parts of this asset, so you may need to update the related parts as well depending on the flexibility of the interaction system you are looking to replace it with.
My system also includes some specialized features like the on screen widget that shows when you get close to an interactable, as well as the auto closing of the window if you move too far away from an open interactable. You will also be disabling the use of pickup all nearby items, and the hold E to pickup one at a time. These are all features related to the interaction side of the system you are disabling by continuing with the details below. If you like these features then you should reconsider working alongside my system instead using the instructions in the previous section.
WARNING: If you understand the above and still wish to continue with the replacement of the included interaction system follow the steps below:
First disable the interact key bindings. Open the input mapping context IMC_InventoryItemSystem in the Blueprints/Input/ folder and delete the IA_InteractClosestNearby and IA_InteractPickupEverything input actions.
Next disable the interaction ping which will show the ui when you are near an interactable. Open AC_InventoryItemSystem, and disconnect the SetTimerByEvent coming out of the SetupInteractionPing event.
At this point you need to update the included interactables blueprints. Go ahead and open up the BP_Interactable blueprint in the Blueprints/Interactables/ folder. This is the base blueprint used by all the included system examples. This blueprint has implemented the BPI_Interactables interface which provides it with the Interact event. This event then calls the Action event which each of its child blueprints then overrides to perform its own actions.
What you should do at this point is add your interact systems blueprint interface to this BP_Interactable blueprint, and have its implemented interaction event just call the Action event that is already here for you. You will need to make sure you hook up the player controller of the player performing the interaction. My blueprint interface and system passes this through, if yours doesn't you will need to get it from your system and feed it into the Action event.
That's it! Now if your interaction system doesn't use a blueprint interface you will need to just call the Action event when you detect the interactable in your interaction system, and make sure to provide the player controller.
If you come across something missing or if something needs a better explanation please let me know.