メインコンテンツまでスキップ

Unreal Engine Module - Add a weekly high score leaderboard - Add weekly leaderboard menu

Last updated on January 13, 2024

What's on the menu

In this section, you will learn how to prepare widgets that you will use to display weekly leaderboards. The widgets are defined in the following classes.

  • First, there is a C++ class called LeaderboardsWidget. This class display buttons to select leaderboard types based on the Byte Wars game modes, which are Single Player, Elimination, and Team Deathmatch. You will use this class to select which leaderboard to be displayed. This is the same class you use in Module: Add an all time high score leaderboard.

    • Header file can be found in /Source/AccelByteWars/TutorialModules/Engagement/LeaderboardEssentials/UI/LeaderboardsWidget.h.
    • CPP file can be found in /Source/AccelByteWars/TutorialModules/Engagement/LeaderboardEssentials/UI/LeaderboardsWidget.cpp.
    • Blueprint widget can be found in /Content/TutorialModules/Engagement/LeaderboardEssentials/UI/W_Leaderboards.uasset.
  • Second, there is a Blueprint widget called W_LeaderboardPeriod. This widget display buttons to select the leaderboard time period. This is the same widget you use in Module: Add an all time high score leaderboard.

    • Blueprint widget can be found in /Content/TutorialModules/Engagement/LeaderboardEssentials/UI/W_LeaderboardPeriod.uasset.
  • Third, there is a C++ class called LeaderboardWeeklyWidget_Starter. You will use this class to display the leaderboard weekly rankings. This class is defined in the following files.

    • Header file can be found in /Source/AccelByteWars/TutorialModules/Engagement/PeriodicLeaderboard/UI/LeaderboardWeeklyWidget_Starter.h.
    • CPP file can be found in /Source/AccelByteWars/TutorialModules/Engagement/PeriodicLeaderboard/UI/LeaderboardWeeklyWidget_Starter.cpp.
    • Blueprint widget can be found in /Content/TutorialModules/Engagement/PeriodicLeaderboard/UI/W_LeaderboardWeekly_Starter.uasset.
  • Finally, there is a C++ class called LeaderboardWidgetEntry. You will use this class to display individual players' rank information, such as the player's rank and score. This is the same class you use in Module: Add an all time high score leaderboard. This class is defined in the following files.

    • Header file can be found in /Source/AccelByteWars/TutorialModules/Engagement/LeaderboardEssentials/UI/LeaderboardWidgetEntry.h.
    • CPP file can be found in /Source/AccelByteWars/TutorialModules/Engagement/LeaderboardEssentials/UI/LeaderboardWidgetEntry.cpp.
    • Blueprint widget can be found in /Content/TutorialModules/Engagement/LeaderboardEssentials/UI/W_LeaderboardEntry.uasset.

Now, let's take a look at more details on how these widgets are constructed.

Leaderboards widget

Below is the preview of the W_Leaderboards Blueprint widget. This widget display buttons to select leaderboard types based on the Byte Wars game modes, which are Single Player, Elimination, and Team Deathmatch.

Leaderboards widget

The buttons above are declared in the LeaderboardsWidget class header file.

protected:
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional, BlueprintProtected = true, AllowPrivateAccess = true))
UCommonButtonBase* Btn_SinglePlayer;

UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional, BlueprintProtected = true, AllowPrivateAccess = true))
UCommonButtonBase* Btn_Elimination;

UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional, BlueprintProtected = true, AllowPrivateAccess = true))
UCommonButtonBase* Btn_TeamDeathmatch;

When those buttons are clicked, it will call the following function. Basically, it will set the leaderboard types based on the game modes and then display the W_LeaderboardPeriod widget to select the leaderboard time period.

void ULeaderboardsWidget::OpenLeaderboardsPeriod(const FString InGameMode)
{
LeaderboardGameMode = InGameMode;

UAccelByteWarsGameInstance* GameInstance = StaticCast<UAccelByteWarsGameInstance*>(GetWorld()->GetGameInstance());
ensure(GameInstance);

UAccelByteWarsBaseUI* BaseUIWidget = GameInstance->GetBaseUIWidget();
ensure(BaseUIWidget);

BaseUIWidget->PushWidgetToStack(EBaseUIStackType::Menu, LeaderboardsPeriodWidgetClass);
}

To get the selected game mode, we will use the following helper function.

static FString GetLeaderboardGameMode() 
{
return LeaderboardGameMode;
}

Leaderboard Period widget

Below is the preview of the W_LeaderboardPeriod Blueprint widget. This widget display buttons to select the leaderboard time period. The time period buttons are generated dynamically when you play the game. In this widget, there are two types of leaderboard time periods: All-Time and Weekly. In this tutorial, we will implement the Weekly leaderboard period.

Leaderboard period widget

Weekly Leaderboard widget

Weekly Leaderboard widget have several states representing each state of the query status: loading, empty, and not empty (showing a list of the ranking). These states are achieved by using our custom Widget Switcher, the UAccelByteWarsWidgetSwitcher. The list itself is done by using a List View that takes an entry widget class and generate the entry dynamically. This widget also contains one entry below the list view to display the current logged-in player rank. Below is the preview of the W_LeaderboardWeekly_Starter Blueprint widget in its loading state.

Weekly leaderboard widget

The components above are declared in the LeaderboardWeeklyWidget_Starter class header file.

protected:
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional, BlueprintProtected = true, AllowPrivateAccess = true))
UAccelByteWarsWidgetSwitcher* Ws_Leaderboard;

UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional, BlueprintProtected = true, AllowPrivateAccess = true))
UListView* Lv_Leaderboard;

Changing the state of this widget is done by calling Ws_Leaderboard->SetWidgetState(). Here's an example on how to change the state to a loading state:

Ws_Leaderboard->SetWidgetState(EAccelByteWarsWidgetSwitcherState::Loading);

Since the leaderboard ranks all of your players, you probably want to limit the leaderboard rank to be displayed. The default limit to be displayed is ten, but you can modify it in the LeaderboardWeeklyWidget_Starter class header file.

UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
int32 ResultLimit = 10;

Leaderboard Entry widget

Used as the entry widget for the list and current logged in player's rank in Weekly Leaderboard widget. This widget shows individual players' rank information, such as their display name, rank, and score. Below is the preview of the W_LeaderboardEntry Blueprint widget.

Leaderboard entry widget

The components above are declared in the LeaderboardWidgetEntry class header file.

protected:
UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional, BlueprintProtected = true, AllowPrivateAccess = true))
UTextBlock* Tb_Rank;

UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional, BlueprintProtected = true, AllowPrivateAccess = true))
UTextBlock* Tb_DisplayName;

UPROPERTY(BlueprintReadOnly, meta = (BindWidgetOptional, BlueprintProtected = true, AllowPrivateAccess = true))
UTextBlock* Tb_Score;

List View requires the entry widget to implement the IUserObjectListEntry interface. If you look at the parent of this widget, the UAccelByteWarsWidgetEntry, you can see that it has the IUserObjectListEntry implemented. In order for the widget to work properly as an entry widget, it needs to implement the NativeOnListItemObjectSet. This function is the setup function. This is where all the UI setup needs to be done. We have already set that up for you, so you can simply use it for any List View or call the NativeOnListItemObjectSet function to set it up manually.

void ULeaderboardWidgetEntry::NativeOnListItemObjectSet(UObject* ListItemObject)
{
Super::NativeOnListItemObjectSet(ListItemObject);

const ULeaderboardRank* LeaderboardRank = Cast<ULeaderboardRank>(ListItemObject);
if (!LeaderboardRank)
{
return;
}

// Display the player's rank. If no rank, display it as #?.
Tb_Rank->SetText(FText::FromString(FString::Printf(TEXT("#%s"),
LeaderboardRank->Rank <= 0 ? TEXT("?") : *FString::FromInt(LeaderboardRank->Rank))));

// Display player's display name.
Tb_DisplayName->SetText(FText::FromString(LeaderboardRank->DisplayName));

// Display the player's score. If no score, display it as empty.
Tb_Score->SetText(FText::FromString(FString::Printf(TEXT("%s"),
LeaderboardRank->Score <= 0 ? TEXT("") : *FString::FromInt((int32)LeaderboardRank->Score))));
}

Ready the UI

In this section, you will learn how to prepare the widgets mentioned before, so you can follow along with the tutorial.

  1. Open the LeaderboardWeeklyWidget_Starter class header file. Then, declare the following functions.

    protected:
    void GetWeeklyRankings();
    void GetPlayerWeeklyRanking();
    void DisplayPlayerWeeklyRank(const ULeaderboardRank* PlayerRank);
  2. Next, open the LeaderboardWeeklyWidget_Starter class CPP file. Create the definition for the GetWeeklyRankings() function. You will use this function to get and display leaderboard weekly rankings around a certain range (e.g. from rank 0 to 10). For now, just let it empty.

    void ULeaderboardWeeklyWidget_Starter::GetWeeklyRankings()
    {
    // TODO: Get weekly leaderboard rankings here.
    UE_LOG_PERIODIC_LEADERBOARD(Warning, TEXT("Get leaderboard weekly rankings is not yet implemented."));
    }
  3. Still in the same file, create the definition for the GetPlayerWeeklyRanking() function. You will use this function to get the logged-in player's weekly rank in case the player is not included in the list retrieved by the GetWeeklyRankings() function (e.g. the player is not included in the top-10). For now, just let it empty.

    void ULeaderboardWeeklyWidget_Starter::GetPlayerWeeklyRanking()
    {
    // TODO: Get the logged-in player's weekly rank here.
    UE_LOG_PERIODIC_LEADERBOARD(Warning, TEXT("Get logged-in player's weekly rank is not yet implemented."));
    }
  4. Next, create the definition for the DisplayPlayerWeeklyRank() function. You will use this function to display the logged-in player's weekly rank specifically on the one entry below the list.

    void ULeaderboardWeeklyWidget_Starter::DisplayPlayerWeeklyRank(const ULeaderboardRank* PlayerRank)
    {
    // Display player weekly rank information.
    const bool bIsRanked = (PlayerRank && PlayerRank->Rank > 0);
    ULeaderboardRank* PlayerRankToDisplay = NewObject<ULeaderboardRank>();
    PlayerRankToDisplay->DisplayName = bIsRanked ? RANKED_MESSAGE.ToString() : UNRANKED_MESSAGE.ToString();
    PlayerRankToDisplay->Rank = bIsRanked ? PlayerRank->Rank : -1;
    PlayerRankToDisplay->Score = bIsRanked ? PlayerRank->Score : -1;

    PlayerRankPanel->SetLeaderboardRank(PlayerRankToDisplay);
    PlayerRankPanel->SetVisibility(ESlateVisibility::HitTestInvisible);
    }
  5. Then, in the NativeOnActivated() function, add the following code. Basically, it will call the GetWeeklyRankings() function when the W_LeaderboardWeekly_Starter is displayed.

    void ULeaderboardWeeklyWidget_Starter::NativeOnActivated()
    {
    ...
    Super::NativeOnActivated();

    // Reset widgets.
    PlayerRankPanel->SetVisibility(ESlateVisibility::Collapsed);
    Ws_Leaderboard->SetWidgetState(EAccelByteWarsWidgetSwitcherState::Empty);
    Lv_Leaderboard->ClearListItems();

    // TODO: Call functionalities to get and display leaderboard weekly rankings.
    GetWeeklyRankings();
    }
  6. Now, build your project and open it in the Unreal Engine Editor. In the Unreal Engine Editor, go to /Content/TutorialModules/Engagement/PeriodicLeaderboard/. There, you will find a data asset called DA_PeriodicLeaderboard. Open it and enable the Is Starter Mode Active. Then, save the data asset again. This will activate the widgets we discussed before, so you can navigate through them when you play the game.

    Activate Tutorial Module Data Asset starter mode

  7. Now, try to play the game in the Unreal Engine Editor and you should be able to navigate like the image below. You should also be able to see the log you just added earlier when you try to view the leaderboard.

    Tutorial Module UIs quick test

    LogPeriodicLeaderboard: Warning: Get leaderboard weekly rankings is not yet implemented.
  8. Congratulations! You set up the widgets correctly. Move on to the next section where you will set up your Admin Portal periodic leaderboard configuration.

Resources