Zurück zum Blog

Schluss mit HTTP Polling: Ein Unreal Engine WebSockets Tutorial für Real-Time Backends

Veröffentlicht am 22. Februar 2026
Schluss mit HTTP Polling: Ein Unreal Engine WebSockets Tutorial für Real-Time Backends

Jeder Multiplayer-Entwickler stößt irgendwann an eine Grenze, an der die Standard-Replication der Unreal Engine einfach nicht mehr ausreicht. Vielleicht benötigen Sie einen globalen serverübergreifenden Chat, eine Live-Matchmaking-Queue, ein Echtzeit-Handelssystem oder einen Live-Ops-Benachrichtigungs-Feed. Wenn Sie versuchen, diese Features mittels HTTP Polling zu implementieren, werden Sie Ihren Game Thread drosseln und Ihren Server mit redundanten, schweren Anfragen überlasten.

HTTP wurde für den zustandslosen Abruf von Dokumenten entwickelt, nicht für Echtzeit-Spieldaten. Einen Server alle 500ms zu pollen, um zu prüfen, ob ein Matchmaking-Match gefunden wurde, erzeugt massiven Overhead. Allein der HTTP-Handshake verschwendet wertvolle Millisekunden, und bei 10.000 gleichzeitigen Spielern wird Ihre Backend-Infrastruktur sofort schmelzen.

Die Lösung sind WebSockets. Ein WebSocket bietet einen persistenten Full-Duplex-Kommunikationskanal über eine einzige TCP-Verbindung. Sobald die Verbindung steht, können Client und Server Daten sofort pushen, was Latenzen unter 50ms bei minimalem Paket-Overhead ermöglicht.

In diesem Unreal Engine WebSockets Tutorial zeigen wir Ihnen, wie Sie das integrierte WebSockets-Modul in C++ implementieren, Background Threading sicher handhaben, JSON-Payloads serialisieren und eine Verbindung zum Backend herstellen, ohne Ihr Spiel zum Absturz zu bringen.

Warum Standard Replication WebSockets nicht ersetzen kann

Die integrierte Netzwerk-Architektur der Unreal Engine ist Weltklasse, aber sie ist strikt für die Kommunikation zwischen Client und Dedicated Server konzipiert. Sie nutzt UDP, um Actor-States zu synchronisieren, RPCs zu verarbeiten und Movement Prediction zu verwalten.

Ihr Dedicated Server ist jedoch nur eine Instanz eines Matches. Was passiert, wenn ein Spieler in Match A einem Spieler in Match B eine Nachricht schicken muss? Was passiert, wenn Sie Ihren Game Client mit einem globalen Backend-Service verbinden müssen, der Player Progression, Economy oder Social Features verwaltet?

Standard-RPCs können nicht mit Standard-Web-Endpoints kommunizieren. Sie benötigen einen externen Communication Layer. Genau deshalb ist das Verständnis der breiteren Architektur entscheidend – ein Konzept, das wir in unserem Guide Beyond The Pixels Why Your Games Backend Is The Secret To Long Term Success vertiefen.

Lassen Sie uns eine robuste WebSocket-Integration von Grund auf aufbauen.

Step 1: Aktivierung der erforderlichen Module

Unreal Engine liefert ein leistungsfähiges WebSockets-Modul mit, das jedoch standardmäßig in C++ Projekten deaktiviert ist. Bevor Sie Code schreiben, müssen Sie dieses Modul Ihrem Build-System bekannt machen.

Navigieren Sie zum Verzeichnis Source/IhrProjektName und öffnen Sie die Datei IhrProjektName.Build.cs. Fügen Sie WebSockets und Json zu den Public Dependency Modules hinzu.

// YourProjectName.Build.cs
using UnrealBuildTool;

public class YourProjectName : ModuleRules
{
    public YourProjectName(ReadOnlyTargetRules Target) : base(Target)
    {
        PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;

        // Add WebSockets and Json modules here
        PublicDependencyModuleNames.AddRange(new string[] { 
            "Core", 
            "CoreUObject", 
            "Engine", 
            "InputCore", 
            "WebSockets",
            "Json",
            "JsonUtilities"
        });
    }
}

Klicken Sie nach dem Speichern mit der rechten Maustaste auf Ihre .uproject-Datei und wählen Sie Generate Visual Studio project files, um sicherzustellen, dass die Engine die neuen Module korrekt verlinkt.

Step 2: Erstellen des WebSocket Component Headers

Anstatt die WebSocket-Logik direkt an einen Actor oder die Game Instance zu binden, ist es Best Practice, eine wiederverwendbare UActorComponent oder ein USubsystem zu erstellen. In diesem Tutorial bauen wir eine UWebSocketClientComponent, die an Ihren Player Controller angehängt werden kann.

Erstellen Sie eine neue C++ Klasse, die von UActorComponent erbt. Im Header müssen wir IWebSocket.h inkludieren und unsere Connection Delegates einrichten.

// WebSocketClientComponent.h
#pragma once

#include "CoreMinimal."
#include "Components/ActorComponent.h"
#include "IWebSocket.h"
#include "WebSocketClientComponent.generated."

DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnMessageReceived, const FString&, Message);

UCLASS( ClassGroup=(Networking), meta=(BlueprintSpawnableComponent) )
class YOURPROJECT_API UWebSocketClientComponent : public UActorComponent
{
    GENERATED_BODY()

public:	
    UWebSocketClientComponent();

    // Blueprint accessible functions
    UFUNCTION(BlueprintCallable, Category = "Network|WebSockets")
    void ConnectToServer(const FString& ServerURL);

    UFUNCTION(BlueprintCallable, Category = "Network|WebSockets")
    void Disconnect();

    UFUNCTION(BlueprintCallable, Category = "Network|WebSockets")
    void SendMessage(const FString& Message);

    // Blueprint event for receiving data
    UPROPERTY(BlueprintAssignable, Category = "Network|WebSockets")
    FOnMessageReceived OnMessageReceived;

protected:
    virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;

private:
    // The actual WebSocket interface pointer
    TSharedPtr<IWebSocket> WebSocket;

    // Internal callback handlers
    void OnConnected();
    void OnConnectionError(const FString& Error);
    void OnClosed(int32 StatusCode, const FString& Reason, bool bWasClean);
    void OnMessage(const FString& Message);
};

Beachten Sie die Verwendung von TSharedPtr<IWebSocket>. Die WebSocket-Implementierung von Unreal setzt stark auf Shared Pointers, um den Lebenszyklus der Verbindung zu verwalten und Memory Leaks zu vermeiden.

Step 3: Implementierung der Connection-Logik

Nun zur .cpp-Datei. Der Kern der WebSocket-Erstellung in Unreal ist der Zugriff auf das FWebSocketsModule unter Angabe von URL und Protokoll.

Wichtig: Wir müssen unsere internen Callback-Funktionen an die Delegates binden, bevor wir Connect() aufrufen.

// WebSocketClientComponent.cpp
#include "WebSocketClientComponent.h"
#include "WebSocketsModule.h"
#include "Async/Async.h"

UWebSocketClientComponent::UWebSocketClientComponent()
{
    PrimaryComponentTick.bCanEverTick = false;
}

void UWebSocketClientComponent::ConnectToServer(const FString& ServerURL)
{
    // Ensure the module is loaded
    if (!FModuleManager::Get().IsModuleLoaded("WebSockets"))
    {
        FModuleManager::Get().LoadModule("WebSockets");
    }

    // Create the WebSocket instance (Protocol is usually "ws" or "wss")
    WebSocket = FWebSocketsModule::Get().CreateWebSocket(ServerURL, TEXT("wss"));

    if (WebSocket.IsValid())
    {
        // Bind delegates
        WebSocket->OnConnected().AddUObject(this, &UWebSocketClientComponent::OnConnected);
        WebSocket->OnConnectionError().AddUObject(this, &UWebSocketClientComponent::OnConnectionError);
        WebSocket->OnClosed().AddUObject(this, &UWebSocketClientComponent::OnClosed);
        WebSocket->OnMessage().AddUObject(this, &UWebSocketClientComponent::OnMessage);

        // Initiate connection
        WebSocket->Connect();
    }
}

Step 4: Die Game Thread Falle (Sicheres Handling von Nachrichten)

Hier stürzen 90% der Spiele ab, wenn WebSockets zum ersten Mal implementiert werden. Die IWebSocket Callbacks (wie OnMessage) werden asynchron in einem Background Thread ausgeführt.

Wenn Sie versuchen, Actor-Transforms zu ändern, ein UMG Widget zu aktualisieren oder Partikel zu spawnen, wird die Unreal Engine eine Thread Assertion auslösen und sofort abstürzen. Die gesamte Gameplay-Logik muss zurück in den Game Thread geleitet werden.

Lösung: Wir kapseln die Logik in AsyncTask(ENamedThreads::GameThread, ...).

void UWebSocketClientComponent::OnMessage(const FString& Message)
{
    // We are currently on a background thread. 
    // Route the execution back to the Game Thread.
    AsyncTask(ENamedThreads::GameThread, [this, Message]()
    {
        // Now we are safe to update UI or broadcast Blueprint delegates
        if (OnMessageReceived.IsBound())
        {
            OnMessageReceived.Broadcast(Message);
        }
        
        UE_LOG(LogTemp, Log, TEXT("WebSocket Received: %s"), *Message);
    });
}

void UWebSocketClientComponent::OnConnected()
{
    AsyncTask(ENamedThreads::GameThread, []()
    {
        UE_LOG(LogTemp, Log, TEXT("WebSocket connected successfully!"));
    });
}

Effizientes Task-Routing ist ein Kernkonzept der Engine-Beherrschung. Mehr dazu in unserem Artikel Leveling Up Your Games Performance Mastering Modern Optimization Techniques.

Step 5: Senden von Daten und Cleanup

Das Senden ist simpel, aber prüfen Sie immer, ob die Verbindung aktiv ist. Zudem müssen WebSockets beim Level-Ende geschlossen werden, um Ghost Connections und Memory Leaks zu vermeiden.

void UWebSocketClientComponent::SendMessage(const FString& Message)
{
    if (WebSocket.IsValid() && WebSocket->IsConnected())
    {
        WebSocket->Send(Message);
    }
    else
    {
        UE_LOG(LogTemp, Warning, TEXT("Cannot send message: WebSocket disconnected."));
    }
}

void UWebSocketClientComponent::Disconnect()
{
    if (WebSocket.IsValid() && WebSocket->IsConnected())
    {
        WebSocket->Close();
    }
}

void UWebSocketClientComponent::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
    Disconnect();
    Super::EndPlay(EndPlayReason);
}

Die Backend-Realität: Warum die Serverseite schwieriger ist

Sie haben nun einen funktionierenden Client. Aber womit verbindet er sich? Einen produktionsreifen WebSocket-Server zu bauen ist deutlich komplexer. Sie müssen Sticky Sessions für Load Balancer handhaben, Redis Pub/Sub für die Kommunikation zwischen Servern implementieren und SSL-Zertifikate für wss:// verwalten.

Mit horizOn sind diese Backend-Services vorkonfiguriert. Sie erhalten skalierbare WebSocket-Endpoints out-of-the-box.

Best Practices für WebSockets in Unreal Engine

  1. Exponential Backoff: Verhindern Sie einen versehentlichen DDoS auf Ihren eigenen Server bei Reconnect-Versuchen.
  2. WSS in Production: Nutzen Sie niemals unverschlüsseltes ws:// in einem Release.
  3. Kleine Payloads: Nutzen Sie JSON oder Binärformate statt riesiger Strings.
  4. Ping/Pong Heartbeats: Überprüfen Sie regelmäßig, ob die TCP-Verbindung noch aktiv ist.
  5. Server-Side Validation: Vertrauen Sie niemals dem Client. Validieren Sie jeden State auf dem Server.

Bereit, Ihr Multiplayer-Backend zu skalieren? Testen Sie horizOn kostenlos oder lesen Sie die API docs.