Setting up the Unreal project #

In this section, we’ll build the prerequisite functionality for our Unreal project, such as getting our player controller stubbed out and making it possible to log into the platform.

Get started #

To help you visualize what you’ll build, below is a screenshot of a barebones party screen.

Screenshot of an example of a party screen in the Unreal game client

This example is simplified to give you an introduction to the game flow. An actual game would have a more sophisticated design, and the player experience may differ significantly.

If you already have an Unreal project set up and integrated with the Pragma SDK, run the update-pragma-sdk.sh script to make the protos we just defined available to your Unreal game.


The following directions propose one possible way to organize and name your code. Adapt the organization and naming to suit your project’s needs.

Create your C++ and Blueprint classes #

Open your Unreal project. In the Unreal Editor Content Browser under C++ Classes, create a new C++ player controller and name it PC_TutorialPlayerController. After the player controller is created, right-click on it in the Content Browser and create a Blueprint class based on it. We recommend creating this Blueprint class in a new directory dedicated to Blueprints.

Next, create another Blueprint class. Choose Game Mode Base as the parent, and name this class GM_TutorialGameModeBase. After it’s created, double-click it to bring up the Class Defaults view. Under Player Controller Class, select PC_TutorialPlayerController.

Add function definitions #

Open your PC_TutorialPlayerController.h header file and edit the includes so that they match the following:

#include "CoreMinimal.h"
#include "PragmaResult.h"
#include "PragmaRuntime.h"
#include "PragmaPlayer.h"
#include "PragmaGameInstanceSubsystem.h"
#include "GameFramework/PlayerController.h"
#include "TutorialPlayerController.generated.h"

Insert the following below GENERATED_BODY():

public:


protected:


private:
	Pragma::FRuntimePtr Runtime;
	Pragma::FPlayerPtr Player;

We will be adding to the header file as we build out the party functionality over the course of this guide.

Define prerequisite functions #

We’ll now define and hook up the necessary function definitions to successfully create a party. Create a Blueprint where you can build your UI. As you follow this guide, create the necessary UI elements so you can view and manipulate the state of the party.

Unreal Boilerplate Functions #

Create the following function declaration in your header file:

public:
    virtual void BeginPlay() override;

Fill in the following function definitions:

void APC_TutorialPlayerController::BeginPlay()
{
	Super::BeginPlay();
	UE_LOG(LogTemp, Display, TEXT("Initializing") );
	Init();
}

This is your standard Unreal Engine boilerplate.

Next, let’s create the Init() function. Insert the following into your header under public.

void Init();

In your source file, add the following:

void APC_TutorialPlayerController::Init()
{
	auto* World = GetWorld();
	if (!World->IsClient())
	{
		return;
	}
	
	Runtime = GetGameInstance()->GetSubsystem<UPragmaGameInstanceSubsystem>()->Runtime();
	Player = Runtime->GetOrCreatePlayer();
	
	if (!ensure(Player))
	{
		return;
	}

	Player->OnConnected.AddUObject(
		this, &ATutorialPlayerController::HandleConnected);
	Player->OnDisconnected.AddUObject(
		this, &ATutorialPlayerController::HandleDisconnected);
}

This initializes the Pragma session and registers event handlers for two specific events: OnConnected and OnDisconnected. When these events occur, the corresponding C++ function is called, which allows us to respond to these events with code.

Connection and Disconnection Handlers #

Let’s create our HandleConnected() and HandleDisconnected() functions. In the header, add the following:

public:
    UFUNCTION(BlueprintImplementableEvent, Category = "Widget")
    void OnPragmaConnected(const UPragmaParty* PragmaParty);

private:
    void HandleConnected();
    void HandleDisconnected();

Then add the following to your source file:

void APC_TutorialPlayerController::HandleConnected()
{
	UE_LOG(LogTemp, Display, TEXT("Pragma Connected") );
	OnPragmaConnected(Player->GameLoopApi().GetParty());
}

Upon successfully connecting to Pragma, we call OnPragmaConnected(). Remember that OnPragmaConnected() is a BlueprintImplementableEvent, so you can handle all appropriate UI logic in your PC_TutorialPlayerController Blueprint class such as transitioning from the login screen to the main menu or displaying the user’s name.

For the purposes of this example, you can use the OnPragmaConnected event in Blueprint as the trigger to switch to the lobby UI.

void ATutorialPlayerController::HandleDisconnected()
{
	UE_LOG(LogTemp, Display, TEXT("HandleDisconnected(): Pragma Disconnected."));
}

This is where we handle disconnection events. In this example, we’re only logging to the console. In a production game, you can add logic as appropriate here, such as transitioning the game client back to the login screen or showing an error message when the disconnection was due to an error.

Login #

We’ll want the ability to enter arbitrary usernames so that we can log in with different accounts, because parties consist of multiple players.

In your header, add the following under protected:

UFUNCTION(BlueprintCallable, Category="Pragma")
void LogIn(const FString& Username);

Then provide the function definition in your source file:

void ATutorialPlayerController::LogIn(const FString& Username)
{
	Player->LogIn(
		EPragma_Account_IdProvider::UNSAFE,
		Username,
		Pragma::FPlayer::FLoggedInDelegate::CreateLambda(
			[this](const TPragmaResult<>& Result) { HandleLoggedIn(Result); }));
}

Build the UI to actually log in. At a minimum, you’ll need a text box to take in a username. The LogIn function can be invoked by a separate button or by pressing the enter key.

As a reminder, if you build the login screen as a separate view from the main menu or party screen, you can use the OnPragmaConnected event to transition away from the login view.