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

3rd person camera, character movement, inventory, and clothing system

Welcome to Sandy Acres
This is a small project game I am currently developing in Unreal Engine 4 to gain experience in implementing gameplay features. The game’s setting is currently loosely set in a post-apocalyptic ‘zombie’ scenario. The final vision for this game will combine action combat, base-building, and RPG elements. The primary goal for working on this game is to increase my proficiency in Unreal Engine 4 and C++, as well as familiarizing myself with game development workflow in general and asset creation.

Third Person Controls
This is a demo of a third person control scheme. The camera follows the player, however it freely rotates with the middle mouse button and the mouse’s movement. The combat system also includes aiming which is done by right clicking to aim-at-mouse on screen. Character movement is accomplished with WASD for 8 direction movement.

Third Person ranged attacks
The aim-at-mouse functionality was an interesting challenge to implement for this third person control scheme. Simply rotating the character to face the position of the mouse hit on the landscape wasn’t the correct option, since the player’s aim would be slightly offset from the cursor, especially when aiming to the left or right (picture a top down oblique view, with a line extending from the character’s feet to the cursor; the bullets would pass above the cursor since the gun is on a different vertical plane than the feet). To solve this I decided to use trigonometry to calculate the rotational offset so that the character’s gun always points in the cursor’s direction; however, there are other ways to solve this problem. Attacks are done simply with a line trace that extends from the gun’s muzzle in the direction of the character’s rotation to check for hits.

Melee attack
Melee attacks are implemented with hitboxes on the melee weapons. During an attack swing, overlaps with enemies are checked to see if the weapon has “hit” anything, and damage is applied accordingly.

Item, loot and inventory system
The item system is implemented with structs that store item properties; i.e. name, image, value, weight, etc. This way, item data can easily be transferred, either to an actor in the world representing that item, like a gun on the floor, or into the player’s inventory. This also makes it easy to display what is in the player’s inventory by accessing the properties to display on screen, like the name, weight, value, image, and quantity of an item.

Modular Clothing
This was accomplished by first creating meshes in Blender that all share the same rig and animations; i.e. body, jacket, pants, etc. They are then imported into UE4 sharing the same skeleton, and switched out during runtime.

Spline mesh actors with world aligned textures
In addition to gameplay features, I also wanted to be able to efficiently build the map and it’s scenery. Fortunately, UE4 has a robust material editor. Using multi-layer blended textures that are world-aligned, scenery objects can be created that will blend in better with its surroundings. Also, large items like walls or roads can be made of smaller repeating meshes without worrying about aligning texture seams.

Click and drag to move
This is an alternative camera movement control scheme, which allows the user to click an area on screen that becomes “fixed” to the mouse cursor in order to move the user’s view around.