Intégration du plugin WebSocket pour Unreal Engine 5

Guide d'implémentation BlueprintWebSocket • Télécharger via Fab Marketplace

Aperçu

BlueprintWebSocket est un plugin réseau asynchrone avancé pour Unreal Engine. Il permet des transferts de données duplex en temps réel avec des serveurs externes en utilisant l'architecture réseau WebSocket, spécialement optimisé pour la création de lobbies multijoueurs en temps réel, de systèmes de chat à haute fréquence et de boucles de télémétrie en direct dans les environnements Unreal Engine 5.

Téléchargez le plugin depuis le Fab Marketplace pour initialiser des éléments réseau en temps réel dans votre espace de travail actuel.

Blueprints

Se connecter à un serveur WebSocket

À l'aide du nœud assistant de latence, vous pouvez vous connecter à une socket réseau active et exécuter immédiatement des chaînes d'exécution automatisées :

Disposition de script Blueprint mappant la connexion WebSocket à l'aide du nœud assistant

Pour des structures logiques personnalisées, créez une instance de socket explicite pour brancher les événements de rappel directement dans les répartiteurs du graphe d'événements :

Blueprint Unreal Engine avancé se connectant avec des affectations de délégué manuelles

Envoyer des données

Configuration du nœud Blueprint routant les messages de chaîne structurelle vers le tampon WebSocket

Reconnexion automatique en cas d'erreur

Gérez automatiquement les déconnexions en définissant des paramètres de nouvelle tentative dans votre séquence de nœuds de base :

Groupe de nœuds réseau Blueprint gérant les boucles de récupération d'état de connexion

C++

Ajouter le module

Ouvrez votre fichier de configuration de build source (<ProjectName>.Build.cs) et ajoutez la dépendance du module dans vos listes d'instructions de compilation :

PublicDependencyModuleNames.Add("BlueprintWebSocket");

Inclure

Exposez les types d'interface en plaçant l'en-tête wrapper dans votre fichier de classe :

#include "BlueprintWebSocketWrapper.h"

Créer un nouveau WebSocket

Instanciez une allocation de tas à l'aide de la méthode de fabrique du plugin :

UBlueprintWebSocket* const WebSocket = UBlueprintWebSocket::CreateWebSocket();

Configurer le WebSocket

Modifiez les structures de métadonnées de transport et les en-têtes d'authentification avant d'invoquer la routine de handshake de connexion :

// Fusionne la map fournie avec la liste d'en-têtes actuelle.
WebSocket->SetHeaders(const TMap<FString, FString> & InHeaders);

// Ajoute une paire Clé / Valeur à la liste d'en-têtes.
WebSocket->AddHeader(const FString & Header, const FString & Value);

// Supprime l'en-tête de la liste d'en-têtes
WebSocket->RemoveHeader(const FString & HeaderToRemove);

Écouter les événements avec des Callbacks

Liez des cibles fonctionnelles aux délégués asynchrones pour recevoir en toute sécurité les modifications d'état des réponses réseau :

Nom de l'événement Signature Description
OnConnectedEvent void Func() Appelé lorsque nous sommes connectés avec succès au serveur WebSocket.
OnConnectionErrorEvent void Func(const FString & Error) Appelé lorsque nous avons échoué à nous connecter au serveur WebSocket.
OnCloseEvent void Func(int64 StatusCode, const FString & Reason, bool bWasClean) Appelé lorsque la connexion avec le serveur a été fermée.
OnMessageEvent void Func(const FString & Message) Appelé lorsque nous avons reçu un message texte.
OnRawMessageEvent void Func(const TArray<uint8> & Data, int32 BytesRemaining) Appelé lorsque nous avons reçu un message binaire.
OnMessageSentEvent void Func(const FString & Message) Appelé juste après l'envoi d'un message.

Comme ces hooks utilisent des Dynamic Multicast Delegates, toute fonction d'écoute liée doit porter la macro de décoration UFUNCTION() pour rester visible dans la pile d'invocation du moteur :

UCLASS()
class MYGAME_API UMyClass : public UObject
{
    GENERATED_BODY()
public:
    // La fonction que nous utilisons pour lier les événements
    void BindEvents();
private:
    // Callbacks
    UFUNCTION() void OnConnected();
    UFUNCTION() void OnConnectionError(const FString & Error);
    UFUNCTION() void OnClosed(int64 StatusCode, const FString & Reason, bool bWasClean);
    UFUNCTION() void OnMessage(const FString & Message);
    UFUNCTION() void OnRawMessage(const TArray<uint8> & Data, int32 BytesRemaining);
    UFUNCTION() void OnMessageSent(const FString & Message);
private:
    UPROPERTY()
    UBlueprintWebSocket* WebSocket;
};

void UMyClass::BindEvents()
{
    // Liez les événements afin que nos fonctions soient appelées lorsque l'événement est déclenché.
    WebSocket->OnConnectedEvent      .AddDynamic(this, &UMyClass::OnConnected);
    WebSocket->OnConnectionErrorEvent.AddDynamic(this, &UMyClass::OnConnectionError);
    WebSocket->OnCloseEvent          .AddDynamic(this, &UMyClass::OnClosed);
    WebSocket->OnMessageEvent        .AddDynamic(this, &UMyClass::OnMessage);
    WebSocket->OnRawMessageEvent     .AddDynamic(this, &UMyClass::OnRawMessage);
    WebSocket->OnMessageSentEvent    .AddDynamic(this, &UMyClass::OnMessageSent);
}

Remarque : Il est recommandé de lier tous les événements que vous utiliserez avant de vous connecter.

Se connecter au serveur WebSocket

Passez l'URI d'endpoint explicite et les sous-chaînes du protocole de communication directement dans la boucle de traitement de connexion :

WebSocket->Connect(TEXT("ws://127.0.0.1:8080/"), TEXT("ws"));

Interrogez les trames d'état en ligne via les vérificateurs de statut fonctionnels :

if (WebSocket->IsConnected())
{
    // Nous sommes connectés.
}
else
{
    // Nous ne sommes pas connectés.
}

Remarque : Vous ne devez pas vous fier à IsConnected() pour gérer la connexion mais au callback OnConnectedEvent .

Envoyer des messages

Transmettez des informations en aval à l'aide de chaînes structurées ou de tampons mémoire directs :

  1. void SendMessage(const FString & Message) : Pour transmettre des formats de données textuelles/JSON.
  2. void SendRawMessage(const TArray<uint8> & Message, const bool bIsBinary) : Pour pousser des structures compressées ou des fichiers de ressources.

Exemple d'implémentation :

// Les données que nous voulons envoyer, vous pouvez les obtenir par programmation.
const FString       StringMessage = TEXT("Hello Server");
const TArray<uint8> BinaryMessage = { 0, 1, 2, 3, 4, 5 };

// Envoyez-le via notre WebSocket.
WebSocket->SendMessage   (StringMessage);
WebSocket->SendRawMessage(BinaryMessage);

Exemple complet

MyClass.h

#pragma once

#include "CoreMinimal.h"
#include "MyClass.generated.h"

class UBlueprintWebSocket;

/**
 * Notre classe personnalisée qui utilise un WebSocket.
 **/
UCLASS()
class MYGAME_API UMyClass : public UObject
{
    GENERATED_BODY()
public:
    void InitializeAndConnectSocket();
private:
    UFUNCTION() 
    void OnConnected();
    UFUNCTION() 
    void OnConnectionError(const FString & Error);
    UFUNCTION() 
    void OnClosed(int64 StatusCode, const FString & Reason, bool bWasClean);
    UFUNCTION() 
    void OnMessage(const FString & Message);
    UFUNCTION()
    void OnRawMessage(const TArray<uint8> & Data, int32 BytesRemaining);
    UFUNCTION()
    void OnMessageSent(const FString & Message);
private:
    UPROPERTY()
    UBlueprintWebSocket* WebSocket;
};

MyClass.cpp

#include "MyClass.h"
#include "BlueprintWebSocketWrapper.h"

void UMyClass::InitializeAndConnectSocket()
{
    WebSocket = UBlueprintWebSocket::CreateWebSocket();
    
    WebSocket->OnConnectedEvent      .AddDynamic(this, &UMyClass::OnConnected);
    WebSocket->OnConnectionErrorEvent.AddDynamic(this, &UMyClass::OnConnectionError);
    WebSocket->OnCloseEvent          .AddDynamic(this, &UMyClass::OnClosed);
    WebSocket->OnMessageEvent        .AddDynamic(this, &UMyClass::OnMessage);
    WebSocket->OnRawMessageEvent     .AddDynamic(this, &UMyClass::OnRawMessage);
    WebSocket->OnMessageSentEvent    .AddDynamic(this, &UMyClass::OnMessageSent);

    WebSocket->AddHeader(TEXT("SomeHeader"), TEXT("SomeValue"));
    WebSocket->Connect(TEXT("ws://127.0.0.1:8080/"), TEXT("ws"));
}

void UMyClass::OnConnected()
{
    UE_LOG(LogTemp, Log, TEXT("We are connected!"));
    WebSocket->SendMessage(TEXT("Hello Server!"));
}

void UMyClass::OnConnectionError(const FString & Error)
{
    UE_LOG(LogTemp, Error, TEXT("Failed to connect: %s."), *Error);
}

void UMyClass::OnClosed(int64 StatusCode, const FString & Reason, bool bWasClean)
{
    UE_LOG(LogTemp, Warning, TEXT("Connection closed: %d:%s. Clean: %d"), StatusCode, *Reason, bWasClean);
}

void UMyClass::OnMessage(const FString & Message)
{
    UE_LOG(LogTemp, Log, TEXT("New message: %s"), *Message);
}

void UMyClass::OnRawMessage(const TArray<uint8> & Data, int32 BytesRemaining)
{
    UE_LOG(LogTemp, Log, TEXT("New binary message: %d bytes and %d bytes remaining."), Data.Num(), BytesRemaining);
}

void UMyClass::OnMessageSent(const FString & Message)
{
    UE_LOG(LogTemp, Log, TEXT("We just sent %s to the server."), *Message);
}

Dépannage

Échec de connexion : Erreur SSL : impossible d'obtenir le certificat de l'émetteur local

Ce problème de sécurité réseau survient parce que les autorités de racine de validation publiques sont omises du bundle de plateforme dans les distributions de jeu entièrement cuites. Résolvez l'intégrité du package de distribution via ces étapes :

  1. Placez votre fichier d'autorité de certification d'autorisation actif (format.pem) dans le chemin source de votre projet : <Project>/Content/Certificates/cacert.pem.
  2. Exposez le sous-répertoire cible au packager de plateforme via Paramètres du projet >Packaging >Répertoires non-assets supplémentaires à copier listes de tableaux.

Assistance

Pour des recommandations de fonctionnalités ou des mises à jour de support fonctionnel, ouvrez un ticket de demande de développeur directement auprès de notre bureau d'ingénierie principal à : pandores.marketplace@gmail.com.