Skip to content
Development
Skill

/unreal

SpacetimeDB Unreal Engine client SDK reference. Use when building Unreal Engine clients that connect to SpacetimeDB.

From plugin
spacetimedb
25k22 skills1 MCP
Install
$ npx -y skills add clockworklabs/spacetimedb --skill unreal --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/unreal

Context preview

The summary Claude sees to decide when to auto-load this skill.

SpacetimeDB Unreal Engine client SDK reference. Use when building Unreal Engine clients that connect to SpacetimeDB.

SKILL.md

unreal.SKILL.md
name: unreal
description: SpacetimeDB Unreal Engine client SDK reference. Use when building Unreal Engine clients that connect to SpacetimeDB.
license: Apache-2.0
metadata:
  author: clockworklabs
  version: "2.0"
  role: client
  language: cpp
  cursor_globs: "**/*.cpp,**/*.h"
  cursor_always_apply: true

SpacetimeDB Unreal Engine Integration

This skill covers Unreal Engine-specific patterns for connecting to SpacetimeDB. For server-side module development, see the `rust-server` or `csharp-server` skills.

---

Installation

Add the SpacetimeDB Unreal SDK as a plugin:

1. Create a `Plugins` folder in your Unreal project root if it does not exist. 2. Copy the `SpacetimeDbSdk` folder into `Plugins/`. 3. Right-click your `.uproject` file and select **Generate Visual Studio project files**. 4. Add `"SpacetimeDbSdk"` to your module's `Build.cs`:

PublicDependencyModuleNames.AddRange(new string[] { "SpacetimeDbSdk" });

---

Generate Module Bindings

spacetime generate --lang unrealcpp \
  --uproject-dir <path_to_uproject_directory> \
  --module-path <path_to_spacetimedb_module> \
  --unreal-module-name <your_unreal_module_name>

This generates C++ bindings in `ModuleBindings/` inside your project. Include the generated header:

#include "ModuleBindings/SpacetimeDBClient.g.h"

Regenerate whenever you change module tables, reducers, or types.

---

GameManager Actor Pattern

The recommended pattern is a singleton Actor that owns the connection. Enable ticking so `FrameTick` is called every frame.

Header (GameManager.h)

#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ModuleBindings/SpacetimeDBClient.g.h"
#include "GameManager.generated.h"

class UDbConnection;

UCLASS()
class AGameManager : public AActor
{
    GENERATED_BODY()
public:
    AGameManager();
    static AGameManager* Instance;

    UPROPERTY(EditAnywhere, Category="SpacetimeDB")
    FString ServerUri = TEXT("127.0.0.1:3000");

    UPROPERTY(EditAnywhere, Category="SpacetimeDB")
    FString DatabaseName = TEXT("my-module");

    UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB")
    UDbConnection* Conn = nullptr;

    UPROPERTY(BlueprintReadOnly, Category="SpacetimeDB")
    FSpacetimeDBIdentity LocalIdentity;

protected:
    virtual void BeginPlay() override;
    virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
public:
    virtual void Tick(float DeltaTime) override;

private:
    UFUNCTION() void HandleConnect(UDbConnection* InConn, FSpacetimeDBIdentity Identity, const FString& Token);
    UFUNCTION() void HandleConnectError(const FString& Error);
    UFUNCTION() void HandleDisconnect(UDbConnection* InConn, const FString& Error);
    UFUNCTION() void HandleSubscriptionApplied(FSubscriptionEventContext& Context);
};

Source (GameManager.cpp)

#include "GameManager.h"
#include "Connection/Credentials.h"

AGameManager* AGameManager::Instance = nullptr;

AGameManager::AGameManager()
{
    PrimaryActorTick.bCanEverTick = true;
    PrimaryActorTick.bStartWithTickEnabled = true;
}

void AGameManager::BeginPlay()
{
    Super::BeginPlay();
    Instance = this;

    FOnConnectDelegate ConnectDelegate;
    BIND_DELEGATE_SAFE(ConnectDelegate, this, AGameManager, HandleConnect);
    FOnDisconnectDelegate DisconnectDelegate;
    BIND_DELEGATE_SAFE(DisconnectDelegate, this, AGameManager, HandleDisconnect);
    FOnConnectErrorDelegate ConnectErrorDelegate;
    BIND_DELEGATE_SAFE(ConnectErrorDelegate, this, AGameManager, HandleConnectError);

    UCredentials::Init(TEXT(".spacetime_token"));
    FString Token = UCredentials::LoadToken();

    UDbConnectionBuilder* Builder = UDbConnection::Builder()
        ->WithUri(ServerUri)
        ->WithDatabaseName(DatabaseName)
        ->OnConnect(ConnectDelegate)
        ->OnDisconnect(DisconnectDelegate)
        ->OnConnectError(ConnectErrorDelegate);

    if (!Token.IsEmpty())
    {
        Builder->WithToken(Token);
    }

    Conn = Builder->Build();
}

void AGameManager::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
    if (Conn) { Conn->Disconnect(); Conn = nullptr; }
    if (Instance == this) { Instance = nullptr; }
    Super::EndPlay(EndPlayReason);
}

void AGameManager::Tick(float DeltaTime)
{
    if (Conn && Conn->IsActive())
    {
        Conn->FrameTick();
    }
}

void AGameManager::HandleConnect(UDbConnection* InConn, FSpacetimeDBIdentity Identity, const FString& Token)
{
    LocalIdentity = Identity;
    UCredentials::SaveToken(Token);

    FOnSubscriptionApplied AppliedDelegate;
    BIND_DELEGATE_SAFE(AppliedDelegate, this, AGameManager, HandleSubscriptionApplied);
    Conn->SubscriptionBuilder()
        ->OnApplied(AppliedDelegate)
        ->SubscribeToAllTables();
}

void AGameManager::HandleConnectError(const FString& Error)
{
    UE_LOG(LogTemp, Error, TEXT("Connection error: %s"), *Error);
}

void AGameManager::HandleDisconnect(UDbConnection* InConn, const FString& Error)
{
    UE_LOG(LogTemp, Warning, TEXT("Disconnected: %s"), *Error);
}

void AGameManager::HandleSubscriptionApplied(FSubscriptionEventContext& Context)
{
    UE_LOG(LogTemp, Log, TEXT("Subscription applied - game state loaded"));
}

---

FrameTick -- Critical

**You must either call `Conn->FrameTick()` every frame in your Actor's `Tick()`, or call `Conn->SetAutoTicking(true)` once at startup.** The SDK queues all network messages and only processes them on tick. Without one of these, no callbacks fire and the client appears frozen.

---

Connection Builder

Build a connection with the builder pattern. All builder methods return pointers for chaining with `->`.

UDbConnection* Conn = UDbConnection::Builder()
    ->WithUri(TEXT("127.0.0.1:3000"))
    ->WithDatabaseName(TEXT("my-module"))
    ->WithToken(SavedToken)                              // optional
    ->WithCompression(ESpacetimeDBCompression::Gzip)     // optional
    ->OnConnect(ConnectDelegate)
    -
Read more
Ships withspacetimedb

Development at the speed of light

Get the whole plugin
Stats
24,990
Stars
1,035
Forks
Active
Maintenance
Rust
Language
just now
Last commit
3y ago
Created

Repo: clockworklabs/spacetimedb