Skip to main content

UI

Overview

The example map(s)' UI is designed for mouse and keyboard. We have two examples available:

  • Top-down (pick up items with the mouse). See /Bolt/Gameplay/Maps/LV_BoltExample_TopDown
  • Third Person (pick up items by focusing on them and pressing E). See /Bolt/Gameplay/Maps/LV_BoltExample_ThirdPerson

From here onward, assume we're talking about the example map's widgets.

note

The example map's widgets are examples. We expect most developers will want to add extra functionality or change the widgets entirely.

Common UI

The example map uses the engine's CommonUI plugin. When migrating widgets to your own project, make sure you have properly set up common UI.

Note

Please double-check this before asking for support: In Project Settings > Engine > General Settings, set Game Viewport Client Class to Common Game Viewport Client.

Design

Widgets for inventories are in the Bolt/Widgets/Inventories folder. These are widgets you will probably want in your own game, whereas widgets in the Bolt/Widgets/HUD folder are generally just for the examples. We will explain some key points here, but we will not go over individual implementations. We highly recommend looking at the widgets themselves to see what you would like to keep/change. The Reference Viewer tool (hotkey: Shift + Alt + R) comes in handy to check how the widgets interact with each other.

Widget Hierarchy

  • Inventory windows are the top level widgets pushed to the HUD. For example, when interacting with a chest, it will show an inventory window.
  • Inventory widgets represent a single inventory. Windows may have one or more inventory widgets.
  • Individual slot widgets.
  • Socket inventories (also known as equipment). These are also item stack widgets. Not all items can have sockets, but for simplicity they are all represented by a socket inventory widget.
  • Sockets. These can hold socketable items.

Widget Hierarchy

Reusability

Inventory and item slot widgets may be reused across different contexts. For example, interacting with a chest uses the same inventory widget as when crafting.

Customizability

Developers may customize the actions that happen when a player interacts with a slot. For example, by default pressing Left Mouse Button will withdraw / deposit / swap items from the hovered slot, depending on what item the player is holding. But if you wanted you could make it use the item instead. See the Inventory Comparison View Model section for details.

Styling

Developers may customize how widgets look without affecting functionality. We use styling from the Common UI plugin.

  • See the /Bolt/Widgets/Styles folder for all styles in the example map.
  • See the Widget Styling section in the Common UI Quickstart Guide for a quick overview of how styling works.

In brief, styles are each data-only blueprints. Common UI's widgets have a Style variable that can be swapped out to change how they look. You may also change the style at runtime by using the SetStyle function.

For custom widgets, you might want to create your own styles. For example, you might want a style for specifically 'simple inventory widgets' that has all of the button styles, text styles, etc. that the widget would need.

Feedback

Slot Overlay

When interacting with item slots, the widgets provide feedback to the player on what would happen. For example:

Equipment slots have a green overlay if you may deposit into them:

Can Be Deposited

Each slot widget asks the Inventory Comparison View Model what operation it will perform and the expected result using the Get Operation Result For Slot function. In the equipment example above, it might return the tag UI.Operation.Deposit and the resulting success/failure if the player decides to click on that slot. Using the Inventory Comparison View Model instead of implementing the overlay in the slot allows us to reuse the slot widget. See the Inventory Comparison View Model section for more details.

Error Messages

Trying to deposit into a slot that's not allowed will give the player a message describing why:

Feedback Message

This is implemented with the plugin's ECResult struct. Whenever calling Bolt's functions, they return an ECResult corresponding to what happened (success or the error that occurred). The requester calls the SendFeedback function on the player controller, which uses the BP_GameplayFeedbackCatalog (folder: /Bolt/Gameplay/Feedback) class to map the ECResult to the error message and sound. Then it plays the sound and tells the HUD to display the error message.

The catalog is a data asset; you may create your own instances to further customize the feedback. To do this, right click on the content browser > Category Create Advanced Asset > Miscellaneous > Data Asset, and select the BP_GameplayFeedbackCatalog class.

The GFC_InventoryOperations asset handles all of the example map's error messages.

note

The default feedback structure (text and sound) will work for most games, but feel free to change it for your own game.

Guide

Opening UI from Game Objects

To start with, we'll go through how to open the UI in game. Click on any of the boxes to interact with them; this will open up a widget for it.

Chest Actors

Internally, the object being interacted calls ViewInventory on the player controller through the BPI_PlayerWithInventory interface. We expect you will want a different interface for other game genres, but this method works for an ARPG.

Afterward, the player controller routes this to the W_HUD, which then creates a new window for the inventory:

Simple Chest

The left side is the chest's inventory and the right side is the player's backpack. Different inventory types can use a different widget; For example, it could use a grid inventory:

Grid Chest

note

If you've looked at Epic's Lyra example, you might be familiar with the node Push Content To Layer For Player. We opted to implement something similar with layers on the HUD. You may use this node instead of the BPI_PlayerWithInventory interface; we avoided it to reduce code dependencies.

Moving Around Items

To move around items, you can left click the slot. Left click changes its behavior based on what's being held and what's in the slot.

  • It will grab the slot's items if the held item slot is empty.
  • It will deposit into the slot if held item slot is not empty and the item stacks can be combined.
  • It will swap if both slots have items and they can't be combined.

This behavior is defined in the Inventory Comparison View Model.

Most slot widgets have buttons for interacting with them. Bolt includes the BLAdvancedButton, which forwards the PointerEvent structure in the OnClicked event. Unlike UMG's default buttons, this enables us to easily handle different inputs like Ctrl + Left Mouse Button, Right Mouse Button, etc. which are common in inventory UIs.

BLAdvancedButton also includes styling from CommonUI.

Held Item

Held Item

The held item is the item attached to the player's cursor. It's stored in the HeldItemInventory on the player state. When the player moves around item stacks in their inventory, they're getting moved to/from the held item inventory.

The Inventory Comparison View Model manages widgets' interactions with the held item inventory; inventory widgets bind to its delegates instead of directly to the held item inventory. This lets the view model determine if items can be moved around depending on the context. For example, if interacting with a vendor, you might want to disallow holding items because they should be staged for sale instead.

Hotbar

The example map includes a simple hotbar for using items. You may assign items to the hotbar by opening the inventory (hotkey: I) and putting consumables into these slots:

Assigning To Hotbar

Assigned items will show at the bottom of the screen:

HUD Hotbar

Pressing the numbers 1-5 will try to use the items in the hotbar slots. By default, only consumable items may be deposited into the hotbar.

You may only assign items to the slots. Depending on the type of game you're making, this might be sufficient for you; we will not be implementing an ability hotbar, as that is out of scope for an item system.

note

The hotbar's input labels don't change, because doing so would require:

  • Icons for each input.
  • UI for remapping keys.

Both of these are out of scope for the plugin. We opted for something simple to demonstrate how a hotbar could be done. Epic's Lyra example has a solid demonstration for key remapping UI.

Inventory Comparison View Model

info
While the name might seem daunting, this class is quite straightforward. It's always spawned along with any inventory windows (when interacting with a chest, for example). It acts as the middleman between the inventory widgets and the inventory controller. More detailed explanations follow.

This class is spawned by inventory windows when they are initialized. It has multiple responsibilities:

  • It maps from inputs to actions.
    • For example, when hovering over an item slot, players pressing LeftMouseButton may withdraw the items from the slot.
  • After the action gets executed, it notifies the player controller of the result; the player controller can opt to display feedback to the player.
  • When some slot widgets get hovered over, they change their overlay's style based on the action's result. See the slot overlay section for more details.

The view model is passed from the window widget to the inventories, to the slots, and all the way down the hierarchy. This way any widgets that need it may hold on to it. Here's a chart that shows how different classes interact with the view model:

View Model Flow

The view model is designed so you may create your own subclass to customize it. We expect that different contexts will want different view models. For example, when interacting with a vendor, you might want Ctrl + Left Mouse Button to stage an item for sale instead of moving it to the other inventory. Doing this with a view model allows us to reuse the inventory widgets.