Devlog 59: UDP with free Object Deliverer plugin in UE

In this post, we look at simple integration of Object Deliverer for UDP connectivity. This will be used to handle motion updates over UDP between UE and java server.

This is a free UE marketplace plugin and it can be found here: https://www.unrealengine.com/marketplace/en-US/product/objectdeliverer

Object Deliverer plugin in UE

I was testing this to communicate with my server using UDP comms.

Custom UDP integration in UE5

Creating connection component

Many UDP libraries I see in marketplace come as an actor component, which I didn’t want.

This library can be integrated with an actor component if you like, or if you prefer like me, create a separate object entirely to handle the UDP comms.

Create a object blueprint like this:

Create a object blueprint

And inside, we will be configuring the sender and receiver, like this:

Creating a connection component object.

As you can see, I created a basic ‘Object’ class and I will use it to configure UDP communication for sending and receiving data.

I will instantiate it from Game Instance, meaning that it will always be live even as I change maps etc.

Here’s my Game Instance code which will create this object.

Game instance which will create the connection component

configure your address and port as you require, for testing mine was:

  • localhost
  • port: 9876

Configuring the UDP sender

This will be achieved in three steps:

Create object deliverer manager
configure deliverybox object sender
start the server
  • First initialize the delivery manager component.
    • Bind on connect/disconnect are not essential
  • Next configure the Delivery box sender object.
    • Important to create of correct type, I send through String.
  • Start the delivery manager, linking to the sender component
    • Configure host/port accordingly
    • Set correct packet rule to your specs

I then simply have a function to send message from this blueprint:

Send UDP message from my server connector

For context, this is how I end up sending these messages:

Calling send UDP message function

For reference, I use this library to convert struct to json:

Struct to JSON library

Configure UDP receiver

This is configured in a very similar fashion to the sender, it also has 3 steps.

Configure the receiver manager
configure the delivery box for receiver
start the UDP receiver
  • configure the object deliverer receiver
    • event bindings here are optional
  • configure the delivery box receiver
    • Specify the delivery box expected message, mine is String
    • Bind the message received here – I will show example of the delegate
  • Start the server
    • Bind on a correct port – it cannot be the same port that’s used by the sender
    • Specify the correct packet rule

Using delegates to pass messages

Inside this server connector object, I configured my UDP receiver and I now want to pass these messages to my components.

I created a connected component blueprint which is just a Actor Component blueprint which will be used as a Parent to all other components I wish to communicate via UDP.

Actor Component which will connect with UDP
Check from parent class whether message can be processed
Process message from actor component

So from my other actor component blueprints, such as the example above, I mainly need to override the Process Message function and define the execution.

Obviously you can customize it as per your requirements, this is just how I routed it.

Server sample code

The entire repo can be found here:

yazoo321/mmo_server_with_micronaut: Hobby project to create mmo server using Java Micronaut with JWT Auth, postgres and mongoDB support (github.com)

The specific code lives inside the UDPServer.java

At the time of writing, I have the following key functions:

Constructor:

    public UDPServer() {
        Thread serverThread =
                new Thread(
                        () -> {
                            try {
                                startServer();
                            } catch (Exception e) {
                                log.error(e.getMessage());
                            }
                        });
        serverThread.start();
    }

Server Listener:

private void startServer() {
        try {
            DatagramSocket socket = new DatagramSocket(UDP_PORT);
            byte[] buffer = new byte[1024];

            while (true) {
                DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
                socket.receive(packet);

                SocketMessage message = reader.readValue(packet.getData(), SocketMessage.class);

                String actorId = getActorId(message);

                if (actorId == null) {
                    log.error("UDP message did not contain actor ID, {}", message);

                    continue;
                }

                socketProcessOutgoingService.processUDPMessage(message);
                log.info("Message received! {}", message);
            }
        } catch (Exception e) {
            e.printStackTrace();
            startServer();
        }
    }

Server Send message:

    public void send(SocketResponse message, InetAddress address) {
        try {
            byte[] data = writer.writeValueAsBytes(message);
            DatagramPacket packet =
                    new DatagramPacket(
                            data, data.length, address, 5555);
            DatagramSocket socket = new MulticastSocket();

            socket.send(packet);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Check out the repository if you’re interested in how things are wired more in-depth. The code will be changing as its being worked on.