Devlog 63: How I made a persistable action bar in UE5

Devlog 63: How I made a persistable action bar in UE5

I’ve previously made an action bar for the game, which was covered in:

Now I want to make the action bar persist the skills even after closing the game.

Making a persistent action bar in UE5

This can be achieved in multiple ways but main thing is that we need to have a persistance service.

You can be fairly creative with how to solve this, for example it can be:

  • using external service provider, such as Playfab Characterer data
  • Hosting SQL server and connecting via UE5 server
  • Hosting standalone service which can provide this functionality

As I already have a custom server I am building, I will simply extend the functionality to support the storage of the action bar data for my characters.

The mmo server code I am using can be found here. It’s mainly the action bar service which deals with this.

The server stores this in MongoDB but most databases will work just fine.

General logic for storing action bar info

We simply need to store information about action bar content for each character. It can perhaps be easier to display with an example.

I will store the information as JSON:

{
  "actorId": "actor1",
  "actionbarId": "slot1",
  "actionbarContent": {
    "skillId": "skill1",
    "itemId": "uniqueItemId"
  }
}   

Each entry will be stored in the database. I could make a List<ActionbarContent> too, which is fine, but it will make individual updates slower, so I prefer to keep them independent, despite technically it being more data to transfer.

Note that I added actionbar content which will help control what the action bar slot can contain. For now, I only support skills (in UE) but in near future, I expect I will be adding items to the action bar too. For items, I will link them using item instance ID – this may have some limitations particularly when items will be consumed, the slot may clear up automatically, which may not be desired behaviour.

The Actionbar ID refers to the slot identifier in UI. So for me it will be simply slot1, slot2, etc.

Of course your implementation can look completely different so design it as per your own requirements.

Bear in mind, I will also have to iterate and improve this system. For example, rather than instance ID, I may change to include item ID and instance ID. I will want to also include counter for availability. For example skill charges available or item count (e.g. potion count). This may be extracted locally from client/inventory component though.

Let’s see how I modelled these in Java which will be reflected in UE structs too:

public class ActorActionbar {

    String actorId;
    String actionbarId;

    ActionbarContent actionbarContent;
}
public class ActionbarContent {

    String skillId;
    String itemId;
}

Unreal Engine action bar

I have a player canvas widget which contains all HUD components including the action bar:

Unreal Engine HUD containing action bar

My actual action bar widget looks like this:

Action bar widget, containing action bar slots

At the moment, the action bar slots are statically placed – I am thinking that later I will add them dynamically.

This is the widget for the action bar slot widget.

Action bar slot widget

Adding update logic on drag and drop

We’ve previously added the drag and drop logic to the action bar items. We’re going to extend this logic to update the server with the updates made.

When we drag a skill out of the action bar, we will clear the bar and therefore update the data with null.

Updating the action bar to server with null

The action bar component is responsible for sending the message to server:

Update action bar slot on server message

Let’s see what happens On Drop – this refers to dropping a skill or item on to the action bar:

On Drop - when it is a skill book item
On drop - item dropped to action bar

So the only possible interactions with action bar is to drag and drop items to the slot. This allows me to encapsulate all updates when these events are triggerered.

This means, when items or skills are dragged or dropped, as long as I update server on each event, then it will always be in sync.

What can we do to improve this?

We can encapsulate this into 1 message rather than 2. However its simpler to do this with above methodology. I will perhaps combine the logic if and when I start hitting many players online.

What do we do on drag and drop?

It’s fairly simple, there are only 2 requests to handle and both are similar.

The key function above is the Update Server Actionbar. We populate the JSON that I shared above. The information will be:

  • actor ID (also can be extracted from session, but I add this for when I potentially have actor pets or similar)
  • Action Slot ID
  • Skill ID
  • Item ID

When we drag a skill out of the action bar, we set skill ID and item ID to null. The server will be able to process this as a DELETE to the record.

When we drag a skill/item in, the server will process this to insert the new record.

Getting action bar contents on startup

When we log in to the character, we want to populate the action bar. So we want to fetch from server (or wherever you store this data) all the action bar data.

I pull this data using the ActionsComponent which I attach to my actors:

Fetch action bar items from server

This is linked to event begin play

Preparing actions bar
Link this to event begin play

This requests the action bar to be sent from server. We now want to receive this message and process it.

Receive response from server and process it
Process update action bar response

In order to get the action bar widget, I created a function to find it and promote it to variable:

Get action bar widget

This makes sure I only do the lookup once. I created it because this component was spawned before the widget was created.

Next, I ask the widget to update the slot data with the response from server:

Update slot with data from server

In order to populate the Action Slot Map, I added all of the slot widgets into the Map variable. This allows for a very quick lookup.

Slots are part of Horizontal Box

As you can see above, the slot widgets are part of the Horizontal Box, which is exposed as a variable.

In order to grab all of them, I could just Get All Children from the Horizontal Box and iterate over them and add to the map.

Adding all slot widgets into Action Slot Map

The key is the Slot ID I assigned to the widget, which is just a custom string variable.

You can see me populate the Slot ID as default variable in the Action Bar Widget Designer:

Alternatively, a simple, yet tedious way is to add them manually like this:

Preparing action slot map

Once the slot is identified, its fairly simple:

Process update skill or item on the slot

The rest of the blueprints are the same as before, but for context, this is how i set the skill image:

Set skill image on slot

Conclusion

We now have a persisting action bar. This means that when we disconnect and re-open the game, the action bar will load the skill information and load it for us.