25. Unreal Engine and MMORPG – how to login into the game

In this post we’re exploring how we can ‘log into’ a game using a custom server.

This is continuation for character creation/selection screen covered here.

Specifically, it’s about the implementation of the ‘Login’ button and having the character enter the game world.

This will be split into few posts, and this will be part 1, so stay tuned for more!

The server used in this post can be found here.

logging into the game world with a character

Getting started – Login button implementation

First of all, design your ‘select character widget’ as you like and have a Login button, that we will keep disabled initially.

Select character screen – Login button disabled by default

It’s disabled initially as we don’t have a character available to ‘login’ with.

Now let’s look into the blueprints for this button.

Login button implementation

What does it do?

  • Create loading screen and add it to viewport
  • Get the character motion, to know WHERE to load the character (map and co-ordinates)
  • Propagate account character, to know appearance info to draw and the motion
  • Open map that we want to load

Let’s go through all of this in order then.

Creating basic loading screen

I cannot stress how ‘basic’ this loading screen is – so design it as per your own requirements. In this case it will be a simple widget component which has a text ‘loading’ and a ‘circular throbber’ component.

Very basic loading screen

Usually, it will consist of a large 2D image to display.

There are no additional blueprints for this widget.

So in above blueprints for ‘Login button implementation’ the first part was simply loading this widget.

Getting character motion

Depending on your server design this part will be different. Basically, you will want to find the APIs that you need to call in order to evaluate what map your character is in as well as the co-ordinates to spawn the character in.

For this purpose, I created an API on the server to ‘Get character motion’ which will return both, the map and co-ordinates of the character.

Let’s check how we can get this data via API. The endpoint for this in my server is:

http://localhost:8081/player-motion/<character_name>

Get character motion API

I updated the create character flow to setup updated values for map name and co-ordinates.

These values will be updated through motion socket implementation, which will be constantly updating characters motion in the game. This will be covered in next post as it’s a relatively complicated piece.

Ok great – we already load the character name and appearance as part of select character screen and now we’ve also got the map to load as well as the co-ordinates to put the character into.

Propagating variables to next map

Ok so we’ve got the character appearance information, map to load and position we want to put the character to on the map.

What we’ll do now is put these variables essentially as ‘global variables’, so they’ll be accessible in the other map(s).

In order to do this, create a Game Instance blueprint.

Create a new blueprint of GameInstance class

Once you’ve created this game instance blueprint class, we will want to set this up to your game.

To set it, click Edit -> Project settings

In the project settings window, you can quickly find it by using the search functionality, just type in instance and it should be one of the first options available.

Just set the Game instance class to your newly created blueprint.

Ok now that you have the game instance configured, let’s add some parameters to this blueprint.

First, let’s define the two parameters that we haven’t created yet, Motion and PlayerMotion.

Motion structure

The above motion is what we’ll need when synchronising character motion in-game. For now we just need the map, and the co-ordinates of where the character is at.

Next, we will have a structure for the PlayerMotion.

Player Motion structure

Notice that the player motion structure references the motion struct that we just looked at. The main addition is the inclusion of the player name, but we also have the information of whether player is online. We may use this information to throw an error, but we will skip this for now.

Again, notice that these structures are directly mimicking the response object from the API:

{
    "playerName": "character2",
    "motion": {
        "map": "dreamscape",
        "x": 34723,
        "y": -69026,
        "z": -20121,
        "pitch": 0,
        "roll": 0,
        "yaw": 0,
        "vx": 0,
        "vy": 0,
        "vz": 0,
        "isFalling": false
    },
    "isOnline": false,
    "updatedAt": "2022-10-19T15:43:10.038Z"
}

From above, we can see that we reference all the relevant pieces of data that we care about.

Ok with the structures created, let’s add them as variables to your Game instance.

Game instance variables

You can see I created two variables in my game instance:

  • AccountCharacter
  • PlayerMotionSnapshot

Notice that I’ve left them as private params. You can either make them public variables, or keep them private as I have and create basic functions for the Getters and Setters. It’s better practice to have the explicit getters/setters, but it will not have a functional difference.

Example for the setter:

Example for setter

Example for getter:

Example for getter

Get character motion in blueprints

Get Character Motion in select character widget

In this part we’re just making the GET request to obtain the characters motion – this is the same request which was displayed in the POSTMAN request.

With the response, you want to parse it into the structure, (optionally) promote it to variable and importantly set it within the Game Mode instance.

Parse the data and send it to MainGameInstance (promote to Global Variable)

And the helper method to create the motion can be found here:

Helper function to convert to PlayerMotion

Now we have both, the selected character object, with appearance data as well as the player motion, indicating where to spawn the character.

Opening map

In order to open the map, you want, it’s very simple. We use the function Open Level (by name).

In my case, the motion structure contains the map name – so I can use that to specify the level to open.

Opening level by name

If you have just 1 map, you can open it using static entry.

Enable the login button

Ok now that all the pieces are in place, let’s enable the button when a user has a valid character selected.

In our case it’s pretty simple – it’s when we render a character, which already does the checks to make sure a character is available to render.

Enable the button after rendering selected character

Test loading the map

So now we have a character that we have selected:

Have a character selected

When I click the login button, I will have a brief Loading screen pop up:

Loading screen pop up when Login is clicked

I’m also able to verify that the response from API is received as expected.

After short delay, my character is loaded in the map.

character loaded in the selected map

In the post we will look at how we can change the character from the default one to the custom character that we have.

Setting character

In the above screenshot we can see that the character loaded is not the same as the one from character selection.

We need to modify the selected character using the Game Mode. To do this, create a new blueprint class with parent Game Mode Base.

Create new Game Mode Base blueprint

I called mine MainGameMode. It’s very likely this game mode will be used throughout many maps.

In this Game Mode blueprint, we can configure the player controller and other settings which will be applied to the map.

So, first thing, let’s prepare the character blueprint that we will be using. I will assume you have a character asset prepared, which perhaps you downloaded from the marketplace store.

I have a collection of them available:

My character asset pack

Let’s copy one of them, in which you will make it the main blueprint for the character.

Make a copy where you will make changes

Ok now you can go back to your Game Mode blueprint and set this up as the default pawn class.

Set up the player controller and default pawn in your game mode

The player controller class can be third person or top down – or whatever you want it to be. These steps are agnostic to the methods of you controlling the character.

Let’s now link this game mode to your map – open up your map and find world settings menu. If you don’t see it, click Window -> World settings from the top menu bar.

Override the game mode for the map

If you click play now – you should load the desired character.

Desired character with the controller is loaded

For quick experimentation, you may want to alter the camera on your character blueprint.

Alter the camera position for your character

Later we can configure a better, more flexible camera option, for now we just want to get something working.

Dynamic spawn and appearance

In the above, we spawn the character, but its still static. We need to:

  • Make the character appear based off where the server tells it to
  • Apply the appearance mesh from select character screen

We can do this by obtaining the information from Game Instance that we prepared earlier.

These changes will be easier and better to apply in the construction script for the character.

Spawning at location

Blueprints for dynamically setting location

The location obtained here is the one that was covered in screenshot titled Parse the data and send it to MainGameInstance (promote to Global Variable).

We can click start and try the game to see if the changes are applied:

Starting the game again puts me in different position

This looks great – we now have dynamically set location based on last recorded position.

Changing appearance dynamically

We’re now going to be re-using the blueprints we created for create character component. Unfortunately, the other blueprint had to be skeletal mesh class, so we’re not able to re-use the components right now – there is a way, but I will go with the dirty copy and paste method.

The way for reference, is to create another base class, which will have this functionality, and have the two blueprints inherit them. Perhaps this is an improvement I will make in near future, but for now I just want to get something working quickly.

The create character skeletal mesh blueprint

Inside that blueprint, we had code on the constructor:

Constructor code

As well as the resolvers:

Resolvers inside the create character

On the bright side the resolvers are separated in a graph, so I can copy the whole thing over. Note that this is not good practice. It’s better to create a class which both can inherit and use, as in this way, every time a new component is introduced, we may need to add code in two places.

If you don’t have these resolvers built yet, they were covered in this post.

After copying the pieces in place, adding the variables in and potentially dealing with some component renaming, this is what we come to:

Constructor blueprint continued

The main additions is to pull the game instance again and get the character info from which we obtain appearance structure. Then we call the method to resolve all appearance.

Also, I did have to modify my refresh animation function to this:

Refresh animation update

This now updates the animation blueprint to use either male or female animation class.

Entering the world as the character

Now if we go into the world as character 1:

First character to enter the world

After clicking Login, this character will enter:

Character 1 enters the world

Next if I log into the world with another character:

Second character enter the world

Then the second character will appear as expected.

Second character enters the game world

And that’s it for this post!

In the next one we’ll look at synchronizing motion.

As always, best of luck with your projects!

1 Comment

Comments are closed