UE4 Tab System
- Oliver Stanton
- Sep 6, 2021
- 3 min read
Updated: Sep 21, 2021
First try:
When making a tab system, I first used an integer variable to store the "SelectedTab", and made new integer variables for each tab. When a tab is pressed, it would set the "SelectedTab" variable to that tab's integer (e.g. second tab is pressed, set SelectedTab == SecondTabVar (= 1, or 2 if 0 is no tab contents)). I used a Widget Switcher component to easily jump between the contents of each tab from different widgets, and this works, although it's hard to add animations this way. Anyway, every Tick I set the Widget Switcher Index to the SelectedTab variable, since they're both integers.
Event Tick with Branches that check if SelectedTab == [TabVar]:

Setting SelectedTab = [TabVar] when clicked:

Now, this does work, but only at a basic level, and although it works, it can be optimised and improved on, and currently supports no kind of animation for the tabs themselves, and a botched animation workaround for the contents of each tab.
Second try:
My second attempt was to make an ID integer variable in the button widget itself, which acted as the variable for each tab, so I don't need to make them and use up space in the main widget. I also started using a checkbox system, which my experiments of making them is in another post. The checkbox system would set the state of the tab to selected or not selected depending on if the checkbox itself was selected or not. This meant I could rely on UE4's own checkboxes instead of my own. However, the problem came with animations. To be able to set the checkbox state from the main widget, I need to have the blueprints which set the tab state in the Tick event. However, this means that every frame, the animations will play, which completely messes everything up, as Tick executes instead of button events like Hover and Clicked. So to be able to play the animations in those button events, I can't have the other animations in the Tick event. Putting the animations in the button events is fine, until you reach the point where you need to change the state from outside the button widget. It changes the state, yes, but it doesn't play the animation to change the state, instead waiting for an unhover event from the button. So using this method works, but has a clear, visual bug which I'll need to experiment more with to fix.
Using the ID variable from the tab widget:

Setting the SelectedTab variable to the tab ID variables:

A problem with animations (how do you only play CampaignEnd when the last selected tab was the Campaign button?!):

Third and most successful try:
My third try was what is seen in this post about GTA V's tab. It uses an enumerator for the list of tabs, and a Switch to state what happens when the enum is == to each option. It's so much better and cleaner than my previous attempts that it fits all on one screenshot!

I set all the tabs that aren't the currently selected one's Selected boolean to false, making them unselected when that specific tab is selected. This lets me just set the enum to something and away I go. Enumerators are incredibly useful because they decrease the chance for user error to almost 0, making them super safe. Switches are also clean and more efficient than a list of branches, so using an enum and Switch together is great.
I'm able to set the Selected boolean of the tabs to false easily because I'm doing the events that handle if it's selected or not in the Tick event, so it happens every frame. If I did it in another event, I'd have to call that event every time.
I did also make an enum and Switch that happened in a function, so all I had to do was call a function and plug in the tabs that I wanted to be in the list, which is better for pretty much all cases, but I prefer being able to see the nodes function individually, instead of a big node that has functionality that I can't see.
Inside the function, essentially the same as the GTA tabs but just in a function instead of in the main Event Graph:

Calling the function when clicked and setting the enum and tab inputs:


Comments