In this post we’re going to be synchronizing characters motion using a custom server.
In the previous post, we’ve implemented the functionality to ‘login’ a player into the game world.
Therefore, its natural we want to make sure the character is synchronized with that game world and can potentially start interacting with other characters in game.
The server that’s used in this example can be found in Github here.
Ok first thing is that in this server implementation, we’ve used WebSockets to communicate with server. This is instead of HTTP protocol, as its with less delay. If you’re using a different server, check the implementation, because this is where it can be VERY different.
If you’re using HTTP protocol, you should use VaRest plugin for comms in UE. This allows you to send http requests easier.
I will be using WebSockets, so I will be using Blueprint WebSockets.
Once you install it to your engine, open up your project, then navigate to Edit -> Plugins
Find the plugin and enable it – you will need to restart UE after applying this change.
Overview of what we need to do
Essentially, we need to be synchronizing our characters motion with the server. This will allow us to pop back into the same location when user logs out and also when there are other nearby players, we’ll be able to start drawing them on the map as well.
So, on our character blueprint we want to do the following:
- Part of constructor, create websocket client
- Configure ‘on connect’ and ‘on message’ events
- Connect to the server
- Construct motion messages
- Send the motion information to server
Implementation
Ok let’s start at constructor, this is connected to the work we’ve done in the previous post, which was spawning the character on the map at the specified location and resolving the appearance.
First, I added a new graph to deal with this work, I called it SynchroniseMotion
.
Let’s create a custom event which we’ll populate shortly, but we’ll reference from our constructor now.
With this event created in the SynchroniseMotion
graph, we can now reference it inside our constructor:
This is continuing off the logic that we’ve built in the constructor in previous post. But the previous post is not a pre-requisite to this one, so don’t worry if you don’t have those pieces.
Ok now let’s look at all the functionality/custom events that we needed to create to support the SynchroniseMotion
graph.
First, I create a function to generate the server URL for me.
Depending on your requirement, this may just be a static string. For me, my URL requires me to set the map that the character is on and the character name.
Let’s cross reference with a POSTMAN request.
We can see that the URL is set to: ws://localhost:8081/v1/player-motion/map1/character2
.
So, the two variables are map
and characterName
– and that’s what you can see are being populated in the function.
Note that I’m obtaining this information from Game Instance
(populated in the last post), but you can make those static for now if you like, to test.
Create Web Socket function is from the plugin – if you don’t have this available, double check that you’ve enabled the plugin.
Bind Connect custom event:
This simply binds event to on connected
– can be used to hook other actions. In this case, I will set Boolean for Websocket connected
which will be pre-requisite in sending events to server.
Bind On Send
This simply prints out the message that’s sent – for now just helps with visibility, but again can be used to hook other events.
Set Update Timer
Essentially when the websocket is connected, we want to start synchronizing all the motion between the client with the server.
The custom event for send
does not have to be split from UpdateServer
custom event, but I did so because I will move the logic around and I don’t want it to be muddled up.
Here we can see that every 0.05 seconds, we will send an update to the server, if the websocket is connected. It does this by:
- update player motion struct, based off character pawn
- construct motion json
- convert json to string
- send message with motion string
In the next post we will also be GETTING motion of nearby characters too – and we’ll update the screen with those results.
Let’s look into functionality for Update Player Motion
.
In this function, it looks busy, but its not too complicated – but it does some really fancy stuff.
Basically, we created a Motion
structure and we’re populating it based on the motion of the character model.
The motion struct was introduced in the previous post, for reference it’s this:
Basically its:
- Get Actor Location (x, y, z co-oridnates)
- Get Actor Rotation pro tip – right click the ‘Return value’ and split struct pin
- Get Actor Velocity (vx, vy, vz)
And once you got those values, just update the motion
struct with that data.
construct motion Json
This is another helper method for converting a Structure object into JSON. It’s sad there’s no easy serializer available for this (if someone knows of one, please comment!).
Note that this json is actually created from VaRest
free plugin. We’re not actually using HTTP calls, but their implementation for json is very helpful.
It won’t be visible in below screenshot, but just for ‘overview’ – I go through each param in the struct and ‘set integer field’ or ‘set boolean field’ etc for each of the parameters.
Ultimately, I put it into json only to convert it to a String:
As that’s what the websocket tool expects.
And that’s it!
Once the messages are sent, we’re synchronising the motion with server.
Let’s test this and go over the findings.
Testing
Back to character selection screen, I am able to select the character and login as before.
Once I login, I will start seeing a bunch of messages sent to server, synchronizing motion of my character.
If I move the character around, I can see all values are changing.
If they don’t, check your function on populating them, inside Update Player Motion
.
Key here is that if I go to a new place, lets say this bridge.
Then I close and restart the game, so again back to character select screen:
When I login, my character is back to the correct location!
So, everything appears to be working as expected.
In the next post I will look to have 2 characters in the map and rendering both characters when they’re nearby.