Unreal: Friends #

This tutorial uses Unreal Engine 5.3 with Pragma Engine 0.3.0 to demonstrate integrating Pragma Engine friend functionality with a third-party game engine. This guide assumes you are proficient with Unreal Editor.

In this tutorial, we’ll expand the MyPlayerController.h header file and MyPlayerController.cpp source file to implement functionality related to the Pragma Engine Friend service.

By the end of the tutorial, our game client will be able to send and receive friend invites, fetch friend data, and make basic and rich presence selections.

About the Unreal Tutorials

The code presented in this tutorial 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.

The functions in this tutorial are built as UFunctions with the Exec and BlueprintCallable specifiers, meaning they can be executed by the in-game console and in a Blueprint or Level Blueprint graph. The Exec specifier is useful for quickly testing your functions.

The example tests in each section are meant to ensure your C++ code is working properly and are unlikely to represent a completed game design. Adapt the organization and naming to suit your project’s needs.

Note that you may need to update your #include statements as you progress through the tutorial.

Get DisplayName and SocialId #

Goal: Get your full display name and social ID to use when testing friend functionality.

  1. In MyPlayerController.h, declare GetFullUsername() and GetSocialId():

    UFUNCTION(Exec, BlueprintCallable, Category="Pragma")
    FString GetFullUsername();
    
    UFUNCTION(Exec, BlueprintCallable, Category="Pragma")
    FString GetSocialId();
    
  2. In MyPlayerController.cpp, define GetFullUsername() and GetSocialId():

    FString AMyPlayerController::GetFullUsername()
    {
    	UE_LOG(LogTemp, Display, TEXT("MyGameClient -- Your full username: %s"),
    		*Player->FullDisplayName());
    	return Player->FullDisplayName();
    }
    
    FString AMyPlayerController::GetSocialId()
    {
    	UE_LOG(LogTemp, Display, TEXT("MyGameClient -- Your social ID: %s"),
    		*Player->SocialId());
    	return Player->SocialId();
    }
    

Test #

To test this functionality using the Unreal in-game console, issue GetFullUsername and GetSocialId for test01 and test02. Record these values to use in later steps.

Send friend invite by username #

Goal: Allow players to send friend invites to other players using the player’s full username (display name and discriminator).

In a real game, display names will likely be available to a player within a game instances, on leaderboards, or communicated through methods outside of Pragma, such as via voice chat or direct message.

Steps #

  1. In MyPlayerController.h, declare SendFriendInviteByUsername(). Have the function accept a username in the form of a string. This string will include the invitee’s display name (e.g. test01) and discriminator (e.g. #6902)

    public:
    	UFUNCTION(Exec, BlueprintCallable, Category="Pragma")
    	void SendFriendInviteByUsername(const FString& FullUsername);
    
  2. In MyPlayerController.cpp, define SendFriendInviteByUsername():

    void AMyPlayerController::SendFriendInviteByUsername(const FString& FullUsername)
    {
    	FString DisplayName, Discriminator;
    	FullUsername.Split("#", &DisplayName, &Discriminator);
    
    	Player->FriendApi().SendFriendInviteByDisplayName(
    		FPragma_Account_DisplayName{DisplayName, Discriminator},
    		UPragmaFriendApi::FOnCompleteDelegate::CreateWeakLambda(
    			this, [DisplayName, Discriminator](const TPragmaResult<> Result)
    			{
    				if (Result.IsSuccessful())
    				{
    					UE_LOG(LogTemp, Display,
    						TEXT("MyGameClient -- Sent friend invite to display name: %s"),
    						*DisplayName);
    				}
    				else
    				{
    					UE_LOG(LogTemp, Error,
    						TEXT(
    							"MyGameClient -- Unable to send friend invite by display name. %s %s %s"
    						),
    						*DisplayName, *Discriminator, *Result.GetErrorAsString());
    				}
    			}));
    }
    

Our SendFriendInviteByUsername() method accepts a string value representing the invitee’s full username (display name plus discriminator). The function splits the provided username into a DisplayName and a Discriminator so it can send the values as a FPragma_Account_DisplayName object to the FriendApi’s SendFriendInviteByDisplayName() method. The FriendApi method facilitates sending the friend invite to the correct player.

Test #

To test this functionality using the Unreal in-game console, as user test01, issue SendFriendInviteByUsername using the player’s full display name (e.g., test02#7136). You’ll see “You received a friend invite from test01.” in the Unreal output log for user test02.

To test this functionality using Unreal Blueprints:

  1. Create a “Send friend invite by username” button with a editable textbox that accepts a username.
  2. Have the “Send friend invite by username” button call your SendFriendInviteByUsername() method with the entered username.
  3. As user test01, enter another user’s full display name (e.g. test03#1942) in the text box and send the invite.

When successfully executed, you’ll see “You received a friend invite from test01.” in your Unreal output log for user test03, along with any on-screen functionality you defined in the Blueprints.

Send friend invite by social ID #

Goal: Allow players to send friend invites to other players using the player’s social ID

In a real game, the SendFriendInviteBySocialId() method would likely be called behind the scenes, for example if a player clicks on another player’s avatar in a party to send them a friend invite. In these situations using a social ID is preferable to using a display name because display names can easily change.

Steps #

  1. In MyPlayerController.h, declare SendFriendInviteBySocialId(). Have the function accept a social ID in the form of a string:

    public:
    	UFUNCTION(Exec, BlueprintCallable, Category="Pragma")
    	void SendFriendInviteBySocialId(const FString& SocialId);
    
  2. In MyPlayerController.cpp, define SendFriendInviteBySocialId():

    void AMyPlayerController::SendFriendInviteBySocialId(const FString& SocialId)
    {
    	Player->FriendApi().SendFriendInviteBySocialId(
    		SocialId,
    		UPragmaFriendApi::FOnCompleteDelegate::CreateWeakLambda(
    			this, [this, SocialId](const TPragmaResult<> Result)
    			{
    				if (Result.IsSuccessful())
    				{
    					UE_LOG(LogTemp, Display,
    						TEXT("MyGameClient -- Sent friend invite to id: %s"),
    						*SocialId);
    				}
    				else
    				{
    					UE_LOG(LogTemp, Error,
    						TEXT("MyGameClient -- Unable to send friend invite by ID. %s"),
    						*Result.GetErrorAsString());
    				}
    			}));
    }
    

Our SendInviteBySocialId() method accepts a string value representing the invitee’s social ID. Using this ID, the function calls the FriendApi’s SendInviteBySocialID() method, which facilitates sending a friend invite to the identified player.

Test #

To test this functionality using the Unreal in-game console, as user test01, issue SendInviteBySocialId using the player’s social ID (e.g., test02#7136). You’ll see “You received a friend invite from test01.” in the Unreal output log for user test02.

To test this functionality using Unreal Blueprints:

  1. Display a list of the party members (including their social IDs) in the player’s current party. You can get a list of party players via the FPragmaParty GetPlayers() method.
  2. Allow a user to click a party player from the list to send them a friend invite.
  3. Have your UI action call your SendInviteBySocialId() method with the social ID of the selected player.
  4. As user test01, click a party player’s display name or associated invite button.

When successfully executed, you’ll see “You received a friend invite from test01.” in your Unreal output log for user test03, along with any on-screen functionality you defined in the Blueprints.

View pending friend invites #

Goal: Allows users to retrieve a list of pending received friend invitations.

Steps #

  1. In MyPlayerController.h, declare the GetFriendInvites():

    public:
    	UFUNCTION(Exec, BlueprintCallable, meta=(Category="Pragma"))
    	TArray<FPragmaFriendOverview> GetFriendInvites();
    
  2. In MyPlayerController.cpp, define GetFriendInvites():

    TArray<FPragmaFriendOverview> AMyPlayerController::GetFriendInvites()
    {
    	using FReceivedInvites = TMap<FString, FPragmaFriendOverview>;
    
    	FReceivedInvites PendingReceivedInvites = *Player->FriendApi().GetReceivedInvites();
    
    	TArray<FPragmaFriendOverview> InviteList;
    
    	for (auto&PendingFriendInvite : PendingReceivedInvites)
    	{
    		FString PendingFriendSocialId = PendingFriendInvite.Value.SocialId();
    
    		InviteList.Add(PendingFriendInvite.Value);
    
    		UE_LOG(LogTemp, Display, TEXT("You have a pending invite from Social ID: %s"), *PendingFriendSocialId);
    	}
    
    	return InviteList;
    }
    

Test #

To test this functionality using the Unreal in-game console, as player 1, send a friend invite to player 2. As player 2, call GetFriendInvites. You’ll see “You have a pending invite from Social ID: " followed by the social ID of player 1.

To test this functionality using Unreal Blueprints, add a “Get friend invites” button and use the returned array to display various friend data, such as display name or social ID.

Accept or decline a friend invite #

Goal: Allow players to accept or decline a friend invite.

Players can respond to friend invites using the inviter’s social ID.

Steps #

  1. In MyPlayerController.h, declare AcceptFriendInvite() and DeclineInvite():

    public:
    	UFUNCTION(Exec, BlueprintCallable, Category="Pragma")
    	void AcceptFriendInvite(const FString& InviterSocialId);
    
    	UFUNCTION(Exec, BlueprintCallable, Category="Pragma")
    	void DeclineFriendInvite(const FString& InviterSocialId);
    
  2. In MyPlayerController.cpp, define AcceptFriendInvite() and DeclineInvite():

    void AMyPlayerController::AcceptFriendInvite(const FString& InviterSocialId)
    {
    	Player->FriendApi().AcceptFriendInvite(
    		InviterSocialId,
    		UPragmaFriendApi::FOnCompleteDelegate::CreateWeakLambda(
    			this, [this, InviterSocialId](const TPragmaResult<> Result)
    			{
    				if (Result.IsSuccessful())
    				{
    					UE_LOG(LogTemp, Display,
    						TEXT("MyGameClient -- Accepted friend invite from %s."),
    						*InviterSocialId)
    				}
    				else
    				{
    					UE_LOG(LogTemp, Error,
    						TEXT("MyGameClient -- Unable to accept friend invite: %s"),
    						*Result.GetErrorAsString());
    				}
    			}));
    }
    
    
    void AMyPlayerController::DeclineFriendInvite(const FString& InviterSocialId)
    {
    	Player->FriendApi().DeclineFriendInvite(
    		InviterSocialId,
    		UPragmaFriendApi::FOnCompleteDelegate::CreateWeakLambda(
    			this, [this, InviterSocialId](const TPragmaResult<> Result)
    			{
    				if (Result.IsSuccessful())
    				{
    					UE_LOG(LogTemp, Display,
    						TEXT("MyGameClient -- Declined friend invite from %s."),
    						*InviterSocialId)
    				}
    				else
    				{
    					UE_LOG(LogTemp, Error,
    						TEXT("MyGameClient -- Unable to decine friend invite: %s"),
    						*Result.GetErrorAsString());
    				}
    			}));
    }
    

Our AcceptFriendInvite() and DeclineFriendInvite() functions accept a string value representing the invite’s social ID, which it uses to call the FriendApi’s AcceptFriendInvite() or DeclineFriendInvite() function.

Test #

To test this functionality using the Unreal in-game console:

  1. If you haven’t already, issue a friend request from one player to another (e.g., have test01 send a friend invite to test03#1943).
  2. As test03, view your pending friend invites to see the inviter’s social ID.
  3. Issue AcceptFriendInvite or DeclineFriendInvite with the inviter’s social ID.

If successful, you should see “Accepted friend invite from [test01’s social ID]” or “Declined friend invite from [test01’s social ID]” in the Unreal output log.

To test this functionality using Unreal Blueprints:

  1. Create an editable text box where the player can enter the social ID of the friend who sent the friend invite.
  2. Create an “Accept friend invite” button that calls our AcceptFriendInvite() function with the social ID value entered in the social ID text box.
  3. Create a “Decline friend invite” button that calls our DeclineFriendInvite() function with the social ID value entered in the social ID text box.

When successfully executed, you’ll see “Accepted friend invite from [test01’s social ID]” or “Declined friend invite from [test01’s social ID]” in the Unreal output log along with any on-screen functionality you defined in the Blueprints.

Get Friend list #

Goal: Allow users to retrieve a list of players on their friend list, identified by social ID.

Steps #

  1. In MyPlayerController.h, declare GetFriends():

    public:
    	UFUNCTION(Exec, BlueprintCallable, meta=(Category="Pragma"))
    	TMap<FString, FPragmaFriend> GetFriends();
    
  2. In MyPlayerController.cpp, define GetFriends():

    TMap<FString, FPragmaFriend> AMyPlayerController::GetFriends()
    {
    	TMap<FString, FPragmaFriend> MyFriendList = *Player->FriendApi().GetFriends();
    
    	UE_LOG(LogTemp, Display, TEXT("Friends: "));
    
    	for (auto&MyFriend : MyFriendList)
    	{
    		UE_LOG(LogTemp, Display, TEXT("%s"), *MyFriend.Key);
    	}
    	return MyFriendList;
    }
    

Test #

To test this functionality using the Unreal in-game console, as a user with one or more friends, issue GetFriends. You’ll see “Friends:” followed by a list of social IDs in the Unreal output log.

To test this functionality using Unreal Blueprints, add a “Get friends” button and use the returned map to display various friend data, such as a list of display names.

Remove a friend #

Goal: Allow players to remove another player from their friends list, using the friend’s social ID.

Steps #

  1. In MyPlayerController.h, declare RemoveFriend():

    public:
    	UFUNCTION(Exec, BlueprintCallable, Category="Pragma")
    	void RemoveFriend(const FString FriendSocialID);
    
  2. In MyPlayerController.cpp, define RemoveFriend():

    void AMyPlayerController::RemoveFriend(const FString FriendSocialID)
    {
    	Player->FriendApi().RemoveFriend(
    		FriendSocialID,
    		UPragmaFriendApi::FOnCompleteDelegate::CreateWeakLambda(
    			this, [this, FriendSocialID](const TPragmaResult<> Result)
    			{
    				if (Result.IsSuccessful())
    				{
    					UE_LOG(LogTemp, Display, TEXT("MyGameClient -- Removed friend: %s."),
    						*FriendSocialID)
    				}
    				else
    				{
    					UE_LOG(LogTemp, Error,
    						TEXT("MyGameClient -- Unable to remove friend: %s"),
    						*Result.GetErrorAsString());
    				}
    			}));
    }
    

Test #

To test this functionality using the Unreal in-game console, as a user with one or more friends, issue RemoveFriend with a friend’s social ID. You’ll see “Friend removed.” in the Unreal output log.

To test this functionality using Unreal Blueprints, add a “Remove as friend” button next to each friend displayed in the UI. Have the button call your RemoveFriend() function with the social ID of the selected player (Player->SocialID). When successfully executed, you’ll see “Friend removed.” in your Unreal output log, along with any on-screen functionality you defined in the Blueprints, such as updating a list of current friends.

Next steps #

Congratulations! You now have a custom Unreal implementation of the Pragma Engine Friend service. Read our Friend service docs to learn about more features you can apply to your game.