Here’s how you can create a Blueprint using C++ for socket communication in Unreal Engine

I have built an environment using the VR Game Mode.

What I aim to do is receive coordinates (x, y, z) from the control of a robot arm in Unreal Engine’s virtual environment and have the real-world robot arm move according to those coordinates.

What I have in mind is to write the communication-related code using C++, turn it into a Blueprint, and then connect it with the existing controller coordinates for further processing.

I’ve created the client-side code so far. Could you provide feedback on it?

I plan to use C++ to create the Blueprint.

The Blueprint I’m making with C++ will handle socket communication with the manipulator’s controller computer, which operates on Python. I’ll write this in code, turn it into a Blueprint, and then use it.

In Unreal Engine, I have already successfully extracted the coordinates of the VR controller. Now, I want to create a socket communication system that will use the Blueprint I create to receive these coordinates and send the coordinate values (x, y, z) to the manipulator controller.

Here’s the code I have created:

// Copyright Epic Games, Inc. All Rights Reserved.

#include "MyBlueprintSocket.h"

// Sets default values
AMyBlueprintSocket::AMyBlueprintSocket()
    : ClientSocket(nullptr), ServerPortNumber(0), bIsConnected(false)
{
    PrimaryActorTick.bCanEverTick = false; // Disable ticking by default
}

// Called when the game starts or when spawned
void AMyBlueprintSocket::BeginPlay()
{
    Super::BeginPlay();
}

bool AMyBlueprintSocket::InitializeSocket(const FString& ServerIP, int32 ServerPort)
{
    // Store server details
    ServerIPAddress = TEXT("113.198.234.193");
    ServerPortNumber = 5000;

    // Resolve the server address
    ISocketSubsystem* SocketSubsystem = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM);
    TSharedRef<FInternetAddr> RemoteAddress = SocketSubsystem->CreateInternetAddr();
    bool bIsValidIP = false;
    RemoteAddress->SetIp(*ServerIPAddress, bIsValidIP);
    RemoteAddress->SetPort(ServerPortNumber);

    if (!bIsValidIP)
    {
        UE_LOG(LogTemp, Error, TEXT("Invalid IP address."));
        return false;
    }

    // Create the socket
    ClientSocket = SocketSubsystem->CreateSocket(NAME_Stream, TEXT("VR Manipulator Socket"), false);
    if (!ClientSocket)
    {
        UE_LOG(LogTemp, Error, TEXT("Failed to create socket."));
        return false;
    }

    // Connect to the server
    bIsConnected = ClientSocket->Connect(*RemoteAddress);
    if (!bIsConnected)
    {
        UE_LOG(LogTemp, Error, TEXT("Failed to connect to server."));
        CloseSocket();
        return false;
    }

    UE_LOG(LogTemp, Log, TEXT("Socket successfully connected to %s:%d"), *ServerIPAddress, ServerPortNumber);
    return true;
}

bool AMyBlueprintSocket::SendCoordinates(float X, float Y, float Z)
{
    if (!bIsConnected || !ClientSocket)
    {
        UE_LOG(LogTemp, Error, TEXT("Socket is not connected."));
        return false;
    }

    // Construct the coordinate data
    FString CoordinateData = FString::Printf(TEXT("%f,%f,%f"), X, Y, Z);
    TCHAR* DataToSend = CoordinateData.GetCharArray().GetData();
    int32 DataSize = FCString::Strlen(DataToSend) * sizeof(TCHAR);

    // Send the data
    int32 BytesSent = 0;
    bool bSuccess = ClientSocket->Send((uint8*)TCHAR_TO_UTF8(DataToSend), DataSize, BytesSent);
    if (!bSuccess)
    {
        UE_LOG(LogTemp, Error, TEXT("Failed to send data."));
        return false;
    }

    UE_LOG(LogTemp, Log, TEXT("Sent %d bytes: %s"), BytesSent, *CoordinateData);
    return true;
}

void AMyBlueprintSocket::CloseSocket()
{
    if (ClientSocket)
    {
        ClientSocket->Close();
        ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->DestroySocket(ClientSocket);
        ClientSocket = nullptr;
        bIsConnected = false;

        UE_LOG(LogTemp, Log, TEXT("Socket connection closed."));
    }
}

// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Networking.h"
#include "Sockets.h"
#include "SocketSubsystem.h"
#include "MyBlueprintSocket.generated.h"

UCLASS()
class DIGITAL_TWIN_API AMyBlueprintSocket : public AActor
{
    GENERATED_BODY()

public:
    // Sets default values for this actor's properties
    AMyBlueprintSocket();

    // Initializes the socket and connects to the server
    UFUNCTION(BlueprintCallable, Category = "Socket")
    bool InitializeSocket(const FString& ServerIP, int32 ServerPort);

    // Sends coordinate data to the server
    UFUNCTION(BlueprintCallable, Category = "Socket")
    bool SendCoordinates(float X, float Y, float Z);

protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;

private:
    // Closes the socket connection
    void CloseSocket();

    // The socket used for communication
    FSocket* ClientSocket;

    // The IP address of the server
    FString ServerIPAddress;

    // The port used for communication
    int32 ServerPortNumber;

    // Indicates if the socket is connected
    bool bIsConnected;
};

Please feel free to share any questions or point out anything that seems off!