Unreal: Friends #
This tutorial uses Unreal Engine 5.3 with Pragma Engine 0.1.0 to demonstrate integrating Pragma Engine party 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.
Get started #
To get started, re-run the update script command:
update-pragma-sdk.sh
Ensure you have a locally running Pragma Engine to test examples as you build each function.
How to use this tutorial #
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.
We’ve built this barebones social screen to help you visualize the functionality presented in this tutorial:
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.
For convenience, we’ve included sample C++ files that contain all the code from this tutorial as well as the login/logout functionality, party functionality, and matchmaking functionality.
Note that you may need to update your #include
statements as you progress through the tutorial.
Implement the Initialize function #
If you haven’t already, implement the InitializeSocial()
function that initializes the Friends and Presence services and sets the player’s basic presence to Online
. See Implement the Initialize function in the Unreal: Presence topic.
Send friend invite by username #
Goal #
Implement a SendFriendInviteByUsername()
function that allows 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.
You can fetch your full username using the GetFullUsername()
function we defined in the Get party and player information step of the Unreal Party tutorial.
Steps #
Declare the
SendFriendInviteByUsername()
function in thepublic
section of yourMyPlayerController.h
file. 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
)UFUNCTION(Exec, BlueprintCallable, Category="Pragma") void SendFriendInviteByUsername(const FString& FullUsername);
Define
SendFriendInviteByUsername()
in yourMyPlayerController.cpp
file:void AMyPlayerController::SendFriendInviteByUsername(const FString& FullUsername) { FString DisplayName, Discriminator; FullUsername.Split("#", &DisplayName, &Discriminator); UPragmaFriendApi::FOnCompleteDelegate SendInviteByDisplayDelegate; SendInviteByDisplayDelegate.BindWeakLambda(this, [DisplayName, Discriminator](TPragmaResult<> Result) { if (Result.IsSuccessful()) { UE_LOG(LogTemp, Display, TEXT("Sent friend invite to display name: %s"), *DisplayName); } else { UE_LOG(LogTemp, Warning, TEXT("Pragma unable to send friend invite by display name. %s %s %s"), *DisplayName, *Discriminator, *Result.Error().ToString()); } }); Player->FriendApi().SendFriendInviteByDisplayName( FPragma_Account_DisplayName{DisplayName, Discriminator}, SendInviteByDisplayDelegate); }
Our SendFriendInviteByUsername()
function 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 GameLoopApi’s SendFriendInviteByDisplayName()
function. The GameLoopApi function 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:
- Create a “Send friend invite by username” button with a editable textbox that accepts a username.
- Have the “Send friend invite by username” button call your
SendFriendInviteByUsername()
method with the entered username. - 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 #
Implement a SendFriendInviteBySocialId()
function that allows players to send friend invites to other players using the player’s social ID. In a real game, this function 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.
You can fetch your social ID using the GetSocialId()
function we defined in the Get party and player information step of the Unreal Party tutorial.
Steps #
Declare the
SendFriendInviteBySocialId()
function in thepublic
section of yourMyPlayerController.h
file. Have the function accept a social ID in the form of a string:UFUNCTION(Exec, BlueprintCallable, meta=(Category="Pragma")) void SendFriendInviteBySocialId(const FString& SocialId);
Define
SendFriendInviteBySocialId()
in yourMyPlayerController.cpp
file:void AMyPlayerController::SendFriendInviteBySocialId(const FString& SocialId) { UPragmaFriendApi::FOnCompleteDelegate SendInviteBySocialDelegate; SendInviteBySocialDelegate.BindWeakLambda(this, [=, this](TPragmaResult<> Result) { if (Result.IsSuccessful()) { UE_LOG(LogTemp, Display, TEXT("Sent friend invite to id: %s"), *SocialId); } else { UE_LOG(LogTemp, Warning, TEXT("Pragma unable to send friend invite by ID. %s"), *Result.Error().ToString()); } }); Player->FriendApi().SendFriendInviteBySocialId( SocialId, SendInviteBySocialDelegate); }
Our SendInviteBySocialId()
function accepts a string value representing the invitee’s social ID. Using this ID, the function calls the GameLoopApi’s SendInviteBySocialID()
function, 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:
- Using the
GetPartyPlayers()
function you defined in the Get party and player information step of the Unreal Parties tutorial, display a list of the party members (including their social IDs) in the player’s current party. - Allow a user to click a party player from the list, or create an associated button, to send an invite.
- Have your UI action call your
SendInviteBySocialId()
method with the social ID of the selected player. - 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 #
Implement a GetFriendInvites()
function that allows users to retrieve a list of pending received friend invitations.
Steps #
Declare the
GetFriendInvites()
function in thepublic
section of yourMyPlayerController.h
file:UFUNCTION(Exec, BlueprintCallable, meta=(Category="Pragma")) TArray<FPragmaFriendOverview> GetFriendInvites();
Define
GetFriendInvites()
in yourMyPlayerController.cpp
file: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 #
Implement a AcceptFriendInvite()
function and a DeclineInvite()
function to allow players to respond to pending friend invites. Players can respond to friend invites using the inviter’s social ID.
Steps #
Declare the
AcceptFriendInvite()
andDeclineInvite()
functions in theprivate
section of yourMyPlayerController.h
file:UFUNCTION(Exec, BlueprintCallable, Category="Pragma") void AcceptFriendInvite(const FString& InviterSocialId); UFUNCTION(Exec, BlueprintCallable, Category="Pragma") void DeclineFriendInvite(const FString& InviterSocialId);
Define
AcceptFriendInvite()
andDeclineInvite()
in yourMyPlayerController.cpp
file:void AMyPlayerController::AcceptFriendInvite(const FString& InviterSocialId) { UPragmaFriendApi::FOnCompleteDelegate RespondFriendInviteDelegate; RespondFriendInviteDelegate.BindWeakLambda(this, [=, this](TPragmaResult<> Result) { if (Result.IsSuccessful()) { UE_LOG(LogTemp, Display, TEXT("Accepted friend invite from %s."), *InviterSocialId) } else { UE_LOG(LogTemp, Warning, TEXT("Unable to respond: %s"), *Result.Error().ToString()); } }); Player->FriendApi().AcceptFriendInvite( InviterSocialId, RespondFriendInviteDelegate ); } void AMyPlayerController::DeclineFriendInvite(const FString& InviterSocialId) { UPragmaFriendApi::FOnCompleteDelegate RespondFriendInviteDelegate; RespondFriendInviteDelegate.BindWeakLambda(this, [=, this](TPragmaResult<> Result) { if (Result.IsSuccessful()) { UE_LOG(LogTemp, Display, TEXT("Declined friend invite from %s."), *InviterSocialId) } else { UE_LOG(LogTemp, Warning, TEXT("Unable to respond: %s"), *Result.Error().ToString()); } }); Player->FriendApi().DeclineFriendInvite( InviterSocialId, RespondFriendInviteDelegate ); }
Our AcceptFriendInvite()
and DeclineFriendInvite()
functions accepts a string value representing the invite’s social ID, which it uses to call the FriendApi’s AcceptFriendInvite()
or DeclineFriendInvite()
function. Alternately, you could design one respond function that accepts a boolean value representing whether to accept or decline the friend invite, similar to the accept/decline party invite function (see Accept or decline a party invite).
Test #
To test this functionality using the Unreal in-game console:
- If you haven’t already, issue a friend request from one player to another (e.g., have
test01
send a friend invite totest03#1943
). - As
test03
, view your pending friend invites to see the inviter’s social ID. - Issue
AcceptFriendInvite
orDeclineFriendInvite
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:
- Create an editable text box where the player can enter the social ID of the friend who sent the friend invite.
- Create an “Accept friend invite” button that calls our
AcceptFriendInvite()
function with the social ID value entered in the social ID text box. - 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 #
Implement a GetFriends()
function that allows users to retrieve a list of players on their friend list, identified by social ID.
Steps #
Declare the
GetFriends()
function in thepublic
section of yourMyPlayerController.h
file:UFUNCTION(Exec, BlueprintCallable, meta=(Category="Pragma")) TMap<FString, FPragmaFriend> GetFriends();
Define
GetFriends()
in yourMyPlayerController.cpp
file: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, call 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 #
Implement a RemoveFriend()
function that removes a player from your friends list. Players remove friends using the friend’s social ID.
Steps #
Declare the
RemoveFriend()
function in thepublic
section of yourMyPlayerController.h
file:UFUNCTION(Exec, BlueprintCallable, Category="Pragma") void RemoveFriend(const FString FriendSocialID);
Define
RemoveFriend()
in yourMyPlayerController.cpp
file:void AMyPlayerController::RemoveFriend(const FString FriendSocialID) { UPragmaFriendApi::FOnCompleteDelegate RespondRemoveFriendDelegate; RespondRemoveFriendDelegate.BindWeakLambda(this, [=, this](TPragmaResult<> Result) { if (Result.IsSuccessful()) { UE_LOG(LogTemp, Display, TEXT("Removed friend: %s."), *FriendSocialID) } else { UE_LOG(LogTemp, Warning, TEXT("Unable to remove friend: %s"), *Result.Error().ToString()); } }); Player->FriendApi().RemoveFriend( FriendSocialID, RespondRemoveFriendDelegate ); }
Test #
To test this functionality using the Unreal in-game console, as a user with one or more friends, call 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.
Sample header and source files #
The following sample files combine the code blocks from this tutorial, along with the functions from the Handle Login and Logout tutorial, the Unreal: Parties tutorial, the Unreal: Matchmaking tutorial, and the Unreal: Presence tutorial.
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.