Getting Steam multiplayer sessions to work in UE4: Some advice

After banging my head against the wall for over a week, poring over dozens of answerhub posts, and plenty more wiki’s on the subject, I finally managed to piece together the full picture on how to get Steam sessions up and running in C++ in UE4, at least in the 4.17 retail build of the engine (and testing using Steam app Id 480). Some tidbits were hidden in youtube comments, or as comments on posts, but I couldn’t find a resource that put it all together. Disclaimer: I can’t guarantee this will fix your problems if you’re using a different version of UE4. Also, I did not have to do any tinkering with my firewall or ports, but everybody’s setup is different. Also, Steam does not work in editor or on a single steam account on a single PC. To test it, I packaged the game then ran it on two different computers with their own unique steam accounts.

Anyways, if you’re like me and have had trouble getting Steam sessions to work in C++, perhaps this advice will help you get through it.
First of all, I followed eXi’s great tutorial on setting up basic sessions in C++. If you haven’t gotten that far, go ahead and follow that link and implement that code into your project, or some of this won’t make sense to you. Be sure to carefully read through it, as it gives a good rundown of the various session functions and callbacks and what they’re doing. There are only a couple minor changed to the code that will help get things running:

Firstly, in the FindSessions function, change the MaxSearchResults to something large, since you are sharing App ID 480 with every other UE4 developer testing their steam game. I changed it to

SessionSearch->MaxSearchResults = 200000;

just to be safe, and it doesn’t seem to noticeably affect search times.

Also, in order to have LAN working properly while logged into steam, you’ll need to append ?bIsLanMatch=1 to your OpenLevel URL if it is a LAN match. This snippet of code should do the trick:

FString levelOptions = "listen";
 if (SessionSettings->bIsLANMatch)
 {
 levelOptions.Append("?bIsLanMatch=1");
 }
 UGameplayStatics::OpenLevel(GetWorld(), FName("Lobby"), true, levelOptions);

Other than that, the code should work as is. However, if you would like to add custom settings to your session, you can set those in the FOnlineSessionSettings when creating a session, and also search for those custom settings when creating your FOnlineSessionSearch. For example you can first set a UPROPERTY to define your custom search setting:

UPROPERTY()
FName SETTING_GAMENAME = TEXT("SETTING_GAMENAME");

Then when creating the session,

SessionSettings->Set(SETTING_GAMENAME, FString(TEXT("MyGame")), EOnlineDataAdvertisementType::ViaOnlineService);

And finally, when searching:

SessionSearch->QuerySettings.Set(SETTING_GAMENAME, FString(TEXT("MyGame")), EOnlineComparisonOp::Equals);

You will also be able to extract those custom settings on the client after searching and finding the sessions, for example in the OnFindSessionsComplete function, to set the game name in the lobby:

FString name; 
(*SessionSearch->SearchResults[SearchIdx].Session.SessionSettings.Settings.Find(SETTING_GAMENAME)).Data.GetValue(name);
customResult.GameName = name;

In this case, customeResult is a custom USTRUCT I made to pass additional information about the found sessions to my blueprint widgets, since the FBlueprintSessionResult struct is limited in the data it passes.

You’ve probably already gone through these steps, but if not you’ll also need to add additional modules in your Game.Build.cs which you can find by browsing through the Solution Explorer in VS, mainly OnlineSubsystem and OnlineSubsystemUtils:

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "PhysXVehicles", "HeadMountedDisplay", "OnlineSubsystem", "OnlineSubsystemUtils", "UMG", "Slate", "SlateCore" });
DynamicallyLoadedModuleNames.Add("OnlineSubsystemSteam");

And in Game.Target.cs add:

bUsesSteam = true;

The other things you’ll need to edit are you DefaultEngine.ini config file. These settings worked for me:

[/Script/Engine.GameEngine]
!NetDriverDefinitions=ClearArray
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="/Script/OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="/Script/OnlineSubsystemUtils.IpNetDriver")
 
[OnlineSubsystem]
DefaultPlatformService=Steam
PollingIntervalInMs=20
 
[OnlineSubsystemSteam]
bEnabled=true
SteamDevAppId=480
GameServerQueryPort=27015
bRelaunchInSteam=false
GameVersion=1.0.0.0
bVACEnabled=1
bAllowP2PPacketRelay=true
P2PConnectionTimeout=90
 
[/Script/OnlineSubsystemSteam.SteamNetDriver]
NetConnectionClassName="/Script/OnlineSubsystemSteam.SteamNetConnection"

And finally, you need to add steam DLL’s to the engine’s third party binaries folders. Follow Rama’s Guide to find out how, but in a nutshell, in the latest retail builds you only need to copy DLL’s into the existing folders. You’ll need to install the steam client on your computer for these DLL’s, and they’ll be found in the root folder of your steam install directory. Copy the 32-bit (steamclient.dll, tier0_s.dll, vstdlib_s.dll) and 64-bit DLL’s (steamclient64.dll, tier0_s64.dll, vstdlib_s64.dll) into their corresponding folders in your UE4 installation. For example

D:/Program Files/Epic Games/UE_4.17/Engine/Binaries/ThirdParty/Steamworks/Steamv139/Win64

IMPORTANT NOTE: When you package your game, be sure to also copy those same DLL’s into your packaged game’s engine, into the corresponding directory depending on whether it is 32 or 64 bit. This was the last bit that got Steam working for me.

And that’s it. Hopefully this guide has helped you get your game ready to test over Steam. I have no idea if this will work after you get greenlit and get your own App Id. If you’re still having problems after this, I feel for you bud. It’s definitely a real headache trying to find all the various bits of information you need to solve what seem like simple tasks in UE4.

Anyways, if you liked this, stay tuned as I’ll be putting up some guides for how I got the UI hooked up to create, find, and join sessions, as well as the simple lobby and chat interface.

Thanks for reading,
Kevin

Leave a Reply

Your email address will not be published. Required fields are marked *