How To Use Sessions In C++

Features for the future

  • Example of network error handling. Like getting disconnected due to a server shutdown.

  • Example of getting information into UMG. Like the Serverlist.

  • Example of extending the GameSession class. Adding more information to your GameSession.

  • Example of extending several other classes that you can make your Session System unique and you will directly understand the ShooterGame after learning all of this.

What is this Tutorial about?

In this Tutorial, I'm going to show you a very basic Code to Create, Find, Join and Destroy Session in C++. So basically we are going to create the Blueprint Session Nodes.

Getting Started

Prepare your Project to use Sessions and OnlineSubsystems

So first of all, we need to get your Project ready to use all of this. I recommend you to start with an empty project, so you can first get an idea how this works, before trying to implement this into your already started project!

Changing the "DefaultEngine.ini"

You can find the "DefaultEngine.ini" file in the Config folder in your top most project folder. You will want to add the following line to it:

[OnlineSubsystem]
DefaultPlatformService=Null

Changing the "YourProjectName.Build.cs"

You can find this file in your Project when you opened it with Visual Studio. You need to add "OnlineSubsystem", "OnlineSubsystemUtils" (for later usage) and the OnlineSubsystem NULL. It should look similar to this:

Changing the "YourProjectName.h"

This file can also be found in the Project when you open it with Visual Studio. You want to change

to

As well as add these two #includes under the "Engine.h" one.

So your file looks something like this:

And that's it for setting up the Project!

My TestProject Setup

So, i want to let you know how my test project is setup and what i am using. I create a new fresh C++ Thirst Person Project and added ONE Class.

I made a child class of "UGameInstance" and called it "UNWGameInstance". (NW = Network). This is what i am referring to from now on and what you will read when seeing my function. Because every function for Creating, Finding,.. Sessions will be placed here.

Code to Create, Find, Join and Destroy Sessions

We are using a lot of Unreal Engine 4's functions here. All these functions are placed in an "SessionInterface" that is designed to handle sessions for different OnlineSubsystems. So although we are using "NULL" here, this should also work with Steam and other Subsystems. At least for the basics that all Subsystems share.

These functions all call a so called "delegate" once they are finished doing what they should do. All Session actions can take some time, so these functions are important. We will create 1-2 delegates, handles and functions for every one of these 4 Sessions operations. They will give us information like if the action was successful or not.

Terms you will read a lot about

Word/Term

Explanation

OnlineSubsystem

OnlineSubsystems are for example "Steam". But you can also use "NULL", which is simply the basic UE4 Subsystem. They all use so called "Wrapper"-Functions. They give us Friend Lists, Unique IDs or Master Server that allow us to find Servers over the Internet and not only on LAN!

Wrapper Functions

Wrapper Functions are something really cool that makes it easy for us to setup the Sessions for all different OnlineSubsystems. While we only need to call "CreateSession", this wrapper function will do the necessary steps to Create a Session in the active Subsystem. So we can create our logic without thinking about Steam or other Subsystems.

Session

A Session is not the Map or the Server itself. A Session is an invisible thing that a Server can Create and a Client can join. They will still need to join the specific Map after joining the Session. A Session is more like an entry in a Database that helps you keeping track of all running Servers.

Session Interface

That is nearly the same as the Session explained above. We will use the Interface instead of the Session itself, because it uses the Wrapper functions we need. We can always get this Internet if we have a valid OnlineSubsystem!

Creating a Session

Yes, let's start with creating a simple Session. I will always post the things we put into the Header file first and after that the logic will fill in with the .cpp File! This will all be placed in the UGameInstance Child class i have created. We don't need other classes.

So what do we need?

Creating a Session | Header File

First we need a function we can use to gather all the settings we want to use for our Session. Let's call this function "HostSession".

The comments explain a lot already, so i will step back from explaining the parameters in the function declarations.

Now we also need the Delegates i talked about earlier. They are used by the "CreateSession" function of the SessionInterface to tell use when the process is done.

So we have a Delegate and a Handle for Creating and Starting a Session. Now we also need a variable we use for the Settings that our Session will have (like LAN or Number of allowed Players):

And we will also add a Constructor to our GameInstance class, which is called when the Object is created. We need this to bind the functions to the delegates!

And finally, we need a function that we bind to the Delegate, so we can perform some actions once we know that the Creation process is complete:

Again, the Comments explain the parameters. These function will have different values for their parameters depending on if the process was successful or not!

Creating a Session | CPP file

Now we fill these functions with logic.

First of all, we will bind the functions to the delegates in our Constructor:

All upcoming bindings for the other operations will be placed in this Constructor, under these two binds.

Now let's have a look at the "HostSession" function we created:

Since i commented everything and this is VERY similar to the upcoming functions, i will only explain this once:

The first thing we do is getting our OnlineSubsystem, because we need the SessionInterface from it. Once we made sure that it is valid, we get the SessionInterface and make sure this and the UsedId are valid.

Then we set a lot of different SessionSettings, like Number of Players etc. After we did this, we going to setting the delegate of the "CreateSessionsComplete" handle to the one we create and that we bound a functions to. So we make sure, that this is the one getting used and called once the "CreateSession" process is finished. We will do this for every Session operation from now on, so i won't explain this again.

Once we did this, we are going to call the "CreateSession" function of the Session Interface and we are done. Now it could take some seconds until it is finished and the Engine calls our Delegate Functions, which we will fill with logic now:

Here again, we will get the OnlineSubsystem and the SessionInterface. This will, again, repeat a lot of times now. Once we made sure that the SessionInterface is valid, we clear the Delegate from the handle, because the call is finished and we want to bind it next time we call "CreateSession". That's why we need to clear it.

After that, we can check if the process was "Successful". If yes, we set the Delegate of the "StartSessionComplete" handle and call the "StartSession" function with the "SessionName" we got. This is already the new Session we created!

This will also take an amount of time but once it is finished, the Engine calls the second Delegate function we created:

Similar to the first one, we get, check and clear things. Then, if everything is done and the process was again successful, we open a new Level with "listen" as a parameter. This is important!

And that's it. Now we created a Session and started it, so we are ready to get Clients on our Server/Session. But for that we need them to find our Session. So next up is "Finding Sessions".

Searching and Finding a Session

So, once we are sure that somewhere we have a Session we can find, we can proceed with the following code.

Searching and Finding a Session | Header File

Function to setup our search and start the searching:

A delegate and a handle for it:

A variable for our SearchSettings which will also contain our SearchResults, once this search is complete and successful:

And finally the function we want to bind to the delegate:

Searching and Finding a Session | CPP File

Now filling this with logic similar to the creation process:

Getting OnlineSubsystem etc and filling the SearchSettings variable. Then setting the Delegate to the handle and tell the SessionInterface to "FindSessions". That's all (:

Once this is finished, the Delegate functions is called. We still need to connect these in the Constructor:

And the function logic:

After getting the OnlineSubsystem and the SessionInterface, we clear the DelegateHandle again and now we can work with the SearchResults. They are stored in the "SessionSearch" variable we created. "SessionSearch->SearchResults" is an array with all found Sessions. You can get several information from this and later on maybe create your own child class of this to add more information! I'm just printing them to the Screen.

That's all for finding Sessions. Now we can go on and try to join one.

Joining a Session

There are different ways you can Join a session, but we will just use a Session result which we can get from the SearchResult array and joined it with help of the SessionInterface. As easy as possible.

Joining a Session | Header file

So the function we are going to use:

The delegates and the function that we bind to it:

Nothing fancy as Settings here. Just the functions and the delegates.

Joining a Session | CPP file

We are doing nothing new here. Since we have no settings, we are not filling any. We are just taking the SearchResult that was passed and call "JoinSession" once we set the delegate to the handle.

And once this is finished, our function gets called again. Again, don't forget to bind it in the constructor:

Here we are doing something new. After getting the OnlineSubsystem and the SessionInterface, we clear the handle. Then we get the PlayerController of the joining Player. Since we are still on this Player, we can just get the FirstLocal one.

The we create an FString that will hold the TravelURL, which we need for a ClientTravel to the Map of the Server. How do we get the TravelURL? Easy: We tell the SessionInterface to create us one. Just pass the SessionName (which at this point is already the one of the Session we joined!) and the FString. Then we can call the ClientTravel function of the PlayerController and we are on the ServerMap, ready to play!

But now we need to also be able to destroy a Session. This is important, because Sessions take Slots on Servers and prevent us from creating new ones or join others as long as they exist.

Destroying a Session

Destroying a Session doesn't need an extra function from us, since we don't need settings or something like that. So we only need the delegate, handle and delegate function:

Destroying a Session | Header file

Destroying a Session | CPP file

Binding the function in the Constructor!

And filling the function with logic:

Doing the same with the OnlineSubsystem and the SessionInterface again and once the destruction was successful, we Open the start level again, which could be the MainMenu for example.

And that's it, this is all you need for a basic setup. You can now create Widgets or so that can use these functions, BUT you can't make these functions BlueprintCallable. You need a second function for each process that is BlueprintCallable.

BlueprintCallable Functions to test this Setup

Creating a Session

Searching and Finding a Session

Joining a Session

Destroying a Session

Last updated

Was this helpful?