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

I was testing this to communicate with my server using UDP comms.
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:

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

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.

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:



- 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:

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

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

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



- 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.



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:
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.