28. UE MMO – how to synchronize players appearance

In the previous post we’ve looked at synchronizing the nearby players motion on our client.

This means that we could see the nearby players move about as we expect, however their appearance was not synchronized between the clients – this is what we’ll focus on achieving in this post.

This is actually not too difficult to achieve because we will be leveraging a lot of pre-existing functionality.

The main things that we have to do is:

  • have a custom event that’s called every x seconds (will set to 0.5 seconds by default)
  • send GET API call to obtain the appearance information for our characters using VaRest plugin
  • apply the appearance information to the proxy characters on screen
Synchronize nearby player appearance

Graph for synchronising appearance

First thing – I added a new graph for synchronizing the nearby players appearance information and renamed the other to specifically cover only motion.

As the name suggests, this graph will be responsible for synchronizing the nearby proxy character appearance data.

First let’s add an entry point for this graph.

This function will run asynchronously – we want to keep the logic separate from others to avoid making any single graph too complicated.

We also make it async to avoid any single call becoming ‘too heavy’. For instance, the motion needs to be synchronized almost real-time, however appearance information doesn’t change as often, so its ok to make it happen less often. We can reduce load quite significantly by splitting this up (though bear in mind any additional HTTP call also has a relatively high overhead).

Next, let’s see what we’re actually trying to get every 0.5 seconds.

Here we see we make a GET request to: http://localhost:8081/player/characters?names=character1,character2

The request has url params for names, which will contain comma separated name values for characters we’re interested to get information of.

The response contains accountCharacters which includes the appearance information that we care about.

Let’s see how we make this call in UE:

VaRest call to get account characters containing appearance information

We can see that we’re using the VaRest plugin in order to create a Json GET request here.

The URL is generated via a helper method – it’s time we start using refactored function calls to generate them.

The helper method is:

The input is an array of strings, in our case it’s an array of keys from NearbyPlayersData where the keys are the character names.

We can use the join string array function in order to nearly put those names together in CSV format.

The host is also refactored to make it easier to change in future, when we will push this to production.

After getting the result from the API call, we want to process it.

Let’s cover what we’re doing here:

  1. Get the account character array information from response
  2. Convert to AccountCharacter struct that we can use in our BP
  3. Update the NearbyPlayersData with the appearance information
  4. Apply the appearance data onto the proxy characters

1 – We saw that the response contained an array called accountCharacters – so we pull it from the payload.

For extra visibility, here’s the expected JSON payload again, notice the accountCharacters object, as well as the appearanceInfo that we ultimately want.

2 – We already covered the ConvertToAccountCharacterResponse function before (part of create/select character widget screens), but here are the helper methods just in case:

3 – Updating the nearby players data struct.

Remember that the variable contains a map of player name as key and Character data as value structure.

The definition of CharacterData is:

which includes AccountCharacter object, which is exactly what we’re pulling.

So once we’ve pulled the AccountCharacter data – we update the definition inside the NearbyPlayersData variable, using the name that’s inside the AccountCharacter as the key.

It can sound confusing so here’s breakdown:

First, get the name from account character and use that to find the nearby player data relevant to this account character.

Next, set the members of CharacterData – here we’re specifically updating the AccountCharacter that we’ve just obtained.

Finally, ADD it back into the map, using the name as the key.

This is because when we updated the value, we updated a copy of the value – if there’s a way to update reference of the value, we would not need to add it back.

4 – applying this appearance information onto the proxies.

Now that we’ve updated the Nearby Players Data struct, we can iterate over each one, and update the proxy characters appearance information and tell each one to Resolve All Appearance.

The resolver was covered part of create character screen post.

Final step is to add an entry point

I added mine to the SynchroniseMotion part of setting up websocket.

It can exist in constructor instead or something like ‘event begin play’.

And that’s it!

Testing

Now, simply start the game, select two characters and enter the game.

You will find that we will re-sync character appearance every 0.5 seconds!

Further improvements?

Many as usual, one big one for instance is to make the resolve character appearance more efficient. Specifically, only start resolving when there’s a noticed change in appearance. Currently it will try applying all appearance information even if nothing’s changed.

4 Comments

  1. wwvsc

    Question – how are you planning on loading the map data – useful for things like preventing players from walking through walls, adding trigger zones, etc

    • hey!
      Simple answer is that I am not.
      Unless you have a larger team, I don’t think this aspect is worth it, if you will try synchronise your movement with the server, not only will it add a lot of additional processing power requirements, but if not done well, it will make player experience a lot worse.

      However, for things like combat with mobs/AI, the idea is to have UE server(s) loaded and playing with the custom server (which are map aware).

      In that way, the UE server is almost like an acting player of the mobs. Furthermore, for the combat, you could do synchronisation with server, so the client will not be responsible for evaluating damage etc, but rather would ‘request’ to attack, or ‘request’ to use skill, and the server will actually validate and process it.

      • reverett

        interesting, but if the UE server is to be loaded anyway, what do we gain by having this secondary system around? seems like we could skip all the character synchronization in that case and just use this system for server selection/character selection

Comments are closed