Course: The EOS Online Subsystem (OSS) Plugin

This course is a walkthrough for integrating and using the Epic Online Services (EOS) Online Subsystem (OSS) plugin in Unreal Engine. The course was written for UE 5.1, though the code should work in future versions of UE, in UE 5.0 and in UE4.27.

https://dev.epicgames.com/community/learning/courses/1px/unreal-engine-the-eos-online-subsystem-oss-plugin

Important Note
I’m maintaining the code on the GitHub repo, but I’m not updating the code snippets in the course content. There will be some minor differences!

1 Like

If you get a 404 on the link, try signing-in first. We’re working on fixing this!

The 404 issue should now be fixed!

Hi, I have a question about presence search.
I have set the bUsesPresence as False in FOnlineSessionSettings when creating session.


But I found in the dedicated server log that it said AddAttribute named (PRESENCESEARCH) with value (), seems no value is passed to it.

And when I check the session in the DEV Portal, I see Join via Presence is enabled, also the PRESENCESEARCH_b attribute is true.

Is it an issue?
Thanks.

This is NOT an issue. I didn’t explain this well at all in the code comments. With bShouldAdvertise set to true, this will supersede the bAllowJoinViaPresence and bAllowJoinViaPresenceFriendsOnly on our backend and set them to true. With bShouldAdvertise set to true, the session is public and can be found by anyone. Sorry for the confusion this caused.

Hi,

I would like to report (small) errors in the documentation:

  • in the chapter “Setting up a dedicated server to host EOS sessions”, the DestroySession() method is not provided. Instead we get a duplicate of the EndPlay() method.
  • in the HandleEndSessionCompleted() method, we clear the “Start” delegate instead of the End delegate: Session->ClearOnEndSessionCompleteDelegate_Handle(StartSessionDelegateHandle);

Thanks

Hey,

Thank you for reporting these issues! I just updated the course content. The GitHub repo will be updated soon. Just a heads up, there is a bug in UnregisterPlayer. You can find the explanation and fix here: UnregisterPlayer() has a bug in it · Issue #14 · EpicGames/EOS-Getting-Started · GitHub

Thanks again, and we really hope you found this course useful!

HI! I just discovered this course, after weeks of banging my head against the wall to get the EOS OSS plugin working, too bad I didn’t see it sooner!
Now I’m trying to implement Leaderboards and Achievements, and I see that should be the next Topic of the course!
Do you already have a release date planned for that chapter? :smiley:
Thanks so much for this course, there is very little documentation on the subject online.

1 Like

It’s currently in review. I don’t have a precise ETA to share, but it should be coming out in the next few weeks. If ever you’re in a jam and need help before, you can open a ticket on our EOSHelp platform: Epic Online Services (EOS) Developer Support

1 Like

Any particular reason you choose to handle the dedicated server stuff in the game-session instead of the game-instance class?

We’ve just updated the content of this course and added sections for:

  • EOS Stats, Achievements and Leaderboards
  • EOS Player and Title Data Storage
  • EOS P2P, Lobbies and Voice
3 Likes

Yes there’s a few reason we opted for AGameSession over a UGameInstance. The project in this course is meant to be an example of a simple multiplayer game, where players join a session to play a match on the same map. Data isn’t persisted across sessions once a session is ended. In other words, the data is relevant to the session, not the entire game. The AGameSession is a nice wrapper around the session interface. As the EOS OSS uses this interface, you can leverage the functions, events, etc… in the base class or use overrides to tweak the behavior as needed (as I did in this course). Let us know if you have follow up questions.

1 Like

I will have to go through this all again. At this moment I have dedicated servers running on PlayFAB but am using the Lyra Example Game as base. The register and update players part for me doesn’t seem to work as of now. And the backend says the servers are not active but they are (I can connect to them with the open {ip:port} command and get destroyed by the bots :sweat_smile:

Hi SebBergy,

Thank you very much for this course! You mentioned in the course, “query stat and achievements,” if you have time, I am curious about how to query stat and achievements. Thanks again!

Any chance we could see a working session search for Dedicated Servers? It’s one of the few things that I can’t get to work.

SessionSearch->bIsLanQuery = false;
SessionSearch->QuerySettings.Set(FName(TEXT(DEDICATEDONLY)), true, EOnlineComparisonOp::Equals);
SessionSearch->QuerySettings.Set(FName(TEXT(LOBBYSEARCH)), false, EOnlineComparisonOp::Equals);

Doesn’t seem to get me any results when trying to find my server.

Also any way to get more info when the server fails to register a player?

LogTemp: Warning: Failed to register player! (From Callback)

Also for the register player. Doesn’t the UniqueID give the EOS string? (Epic account id + eos player user id (PUID with a | separator? Wouldn’t this always fail the register player part?)

Hey! Yes, with Epic Account Services being used, the UniqueId is “EpicAccountId | EOS PUID”. In FOnlineSessionEOS::RegisterPlayers() we have some code that will retrieve the EOS PUID
from the UniqueId and use this to register the player. If you’re running into an issue registering your player on the EOS backend, there should be a hint in your logs. You can also attach to your game and check the EOS_EResult in Data->ResultCode in the CallbackObj.

I’m a bit confused by your code to search for a dedicated server session? Why do you have LOBBYSEARCH in your QuerySettings?

I’ll update here with some code for both later this week!

1 Like

Hi and thanks for responding, I already have it working :slight_smile: I split the string so I will get both the Epic Account ID and the Player PUID.

I have the servers working / hosted on PlayFAB all is working fine (except the search). I define LOBBYSEARCH false ? and Dedicated to true? Or should I simply omit the LOBBYSEARCH all together.?

Here is some code for Stats. I’ll work on getting some code for achievements by end of week.

// Additional code to query stats - Example not included in course 
void AEOSPlayerState::QueryStats(TArray<FString> StatNames)
{
	// This function will query EOS Stats
	IOnlineSubsystem* Subsystem = Online::GetSubsystem(GetWorld());
	IOnlineIdentityPtr Identity = Subsystem->GetIdentityInterface();
	IOnlineStatsPtr Stats = Subsystem->GetStatsInterface();

	// Check if player is online before trying to update stat 
	FUniqueNetIdPtr NetId = Identity->GetUniquePlayerId(0);

	if (!NetId || Identity->GetLoginStatus(*NetId) != ELoginStatus::LoggedIn)
	{
		return;
	}

	// Same idea as UpdateStats, use an inline lambda - We are only querying for local player only in this example.
	// You need to pass in a list of StatNames. Querying for all stats is not supported. 

	TArray<TSharedRef<const FUniqueNetId>> Users;
	Users.Add(NetId.ToSharedRef());

	Stats->QueryStats(NetId.ToSharedRef(),Users, StatNames,
		FOnlineStatsQueryUsersStatsComplete::CreateLambda([](
			const FOnlineError& QueryResult,
			const TArray<TSharedRef<const FOnlineStatsUserStats>>& UsersStats)
			{
				if (!QueryResult.bSucceeded)
				{
					UE_LOG(LogTemp, Warning, TEXT("Error querying player statistics: %s"), *QueryResult.ErrorCode);
					return; 
				}

				// double loop to loop through all users and all stats
				for (auto UserStats : UsersStats)
				{
					// Account we are about to loop through stats
					FUniqueNetIdRef NetId = UserStats->Account;

					for (auto StatNameValuePair : UserStats->Stats)
					{
						FString StatName = StatNameValuePair.Key;
						FVariantData StatValue = StatNameValuePair.Value;
					}
				}
			}));
}
2 Likes